Statistics
| Branch: | Revision:

chunker-player / event_http / event_http_client.c @ 59c85ad1

History | View | Annotate | Download (5.63 KB)

1
/**
2
 * @file event_http_client.c
3
 *
4
 * libevent-based simple http client.
5
 *
6
 * No threads, thus it is based on callbacks and timer events
7
 *
8
 * Napa-Wine project 2009-2010
9
 * @author: Giuseppe Tropea <giuseppe.tropea@lightcomm.it>
10
 * @author: Bakay Árpád <arpad.bakay@netvisor.hu>
11
 */
12

    
13
#include <stdio.h>
14
#include <string.h>
15
#include <sys/socket.h>
16
#include <netinet/in.h>
17

    
18
#include "chunk_external_interface.h"
19
#include "ul_commons.h"
20

    
21
int ulEventHttpClientSetup(const char *address, unsigned short port, struct evhttp_connection **htc) {
22
  struct evhttp_connection *local_htc = NULL;
23
  debug("Setting up event-based http client towards %s:%d", address, port);
24
  local_htc = evhttp_connection_base_new(eventbase, address, port);
25
  //WARN i am not sure that if anything goes wrong the pointer stays at NULL
26
  if(local_htc != NULL) {
27
    //fill return value
28
    *htc = local_htc;
29
    info("Event-based http client towards %s:%d has been setup", address, port);
30
    return UL_RETURN_OK;
31
  }
32
  else {
33
    error("Setup of event-based http client towards %s:%d FAILED", address, port);
34
    return UL_RETURN_FAIL;
35
  }
36
}
37

    
38

    
39
int ulEventHttpClientPostData(uint8_t *data, unsigned int data_len, struct evhttp_connection *htc, const char *addr, const int port, const char *path) {
40
  struct sockaddr_in *remote=NULL;
41
  int sock;
42
  int tmpres=0;
43
  char *post=NULL;
44
  int post_size=0;
45

    
46
  if((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0){
47
    error("Can't create TCP socket");
48
    perror(NULL);
49
    return UL_RETURN_FAIL;
50
  }
51
  remote = (struct sockaddr_in *)malloc(sizeof(struct sockaddr_in *));
52
  if(remote == NULL) {
53
    error("Can't allocate memory for remote struct");
54
    close(sock);
55
    return UL_RETURN_FAIL;
56
  }
57
  remote->sin_family = AF_INET;
58
  tmpres = inet_pton(AF_INET, addr, (void *)(&(remote->sin_addr.s_addr)));
59
  if(tmpres < 0) {
60
    error("Can't set remote->sin_addr.s_addr");
61
    free(remote);
62
    close(sock);
63
    return UL_RETURN_FAIL;
64
  }
65
  else if(tmpres == 0) {
66
    fprintf(stderr, "%s is not a valid IP address\n", addr);
67
    free(remote);
68
    close(sock);
69
    return UL_RETURN_FAIL;
70
  }
71
  remote->sin_port = htons(port);
72

    
73
  if(connect(sock, (struct sockaddr *)remote, sizeof(struct sockaddr)) < 0){
74
    error("Could not connect");
75
    free(remote);
76
    close(sock);
77
    return UL_RETURN_FAIL;
78
  }
79

    
80
  if( (post_size = build_post_query(&post, addr, port, path, data, data_len)) == -1) {
81
    error("Could not allocate post buffer");
82
    free(remote);
83
    close(sock);
84
    return UL_RETURN_FAIL;
85
  }
86

    
87
  //Send the query to the server
88
  int sent = 0;
89
  while(sent < post_size) {
90
    tmpres = send(sock, post+sent, post_size-sent, 0);
91
    if(tmpres == -1){
92
      error("Can't http send post query");
93
      free(post);
94
      free(remote);
95
      close(sock);
96
      return UL_RETURN_FAIL;
97
    }
98
    sent += tmpres;
99
  }
100

    
101
  free(post);
102
  free(remote);
103
  close(sock);
104
  return UL_RETURN_OK;
105
}
106

    
107
int build_post_query(char **post, char *addr, int port, char *path, uint8_t *data, unsigned int data_len)
108
{
109
  char host[UL_URL_SIZE];
110
  char len[UL_URL_SIZE];
111
  char *header;
112
  char *postpath = path;
113
  char *tpl = "POST /%s HTTP/1.0\r\nHost: %s\r\nUser-Agent: Napa-WinePEER/0.1\r\nContent-Length: %s\r\n\r\n";
114
  int header_size=0;
115

    
116
  if(postpath[0] == '/') {
117
    //Removing leading slash
118
    postpath = postpath + 1;
119
  }
120
//  sprintf(host, "localhost:%d\0", port);
121
  sprintf(host, "%s:%d\0", addr, port);
122
  sprintf(len,"%d\0", data_len);
123
  // -6 is to consider the %s %s %s in tpl (6 extra chars)
124
  // the ending \0 is not to be accounted for since it gets overwritten by the data block
125
  header_size = strlen(host)+strlen(postpath)+strlen(len)+strlen(tpl)-6;
126
  if( ((*post) = (char *)malloc(header_size + data_len)) == NULL ) {
127
    return -1;
128
  }
129
  sprintf(*post, tpl, postpath, host, len);
130
  debug("post header is: %s", *post);
131
  memcpy(*post+header_size, data, data_len);
132
  return header_size + data_len;
133
}
134

    
135
/*
136
int ulEventHttpClientPostData(uint8_t *data, unsigned int data_len, struct evhttp_connection *htc, const char *addr, const int port, const char *path) {
137
  char nbuf[UL_URL_SIZE];
138
  char peer_addr[UL_URL_SIZE];
139
  uint16_t peer_port;
140
  struct evhttp_connection *local_htc = NULL;
141
  struct evhttp_request *reqobj = NULL;
142
  struct evbuffer *output_buffer;
143
        int ret = UL_RETURN_FAIL;
144

145
  local_htc = evhttp_connection_base_new(eventbase, addr, port);
146
  if(local_htc == NULL) {
147
    error("Setup of event-based http client towards %s:%d FAILED", addr, port);
148
    return UL_RETURN_FAIL;
149
  }
150

151
  //i hope passing two NULLs is ok for initializing
152
  reqobj = evhttp_request_new(NULL, NULL);
153
  if(reqobj != NULL) {
154
    info("http request container initialized");
155
  }
156
  else {
157
    error("http request container initialization FAILED");
158
    return UL_RETURN_FAIL;
159
  }
160
  reqobj->kind = EVHTTP_REQUEST;
161

162
  output_buffer = evhttp_request_get_output_buffer(reqobj);
163
  // put data into the request
164
  evbuffer_add(output_buffer, data, data_len);
165

166
  debug("prepared an http request for %d bytes", data_len);
167

168
  //fill up the request's headers
169
  //evhttp_connection_get_peer(htc, &peer_addr, &peer_port);
170
  sprintf(nbuf, "%s:%d\0", addr, port);
171
  evhttp_add_header(reqobj->output_headers, "Host", nbuf);
172
  debug("filled Host header: %s", nbuf);
173

174
  sprintf(nbuf,"%d\0", data_len);
175
  evhttp_add_header(reqobj->output_headers, "Content-Length", nbuf);
176
  debug("filled Content-Length header: %s", nbuf);
177

178
  //evhttp_make_request returns -1 in case of fail and 0 for success
179
  if( ret = evhttp_make_request(local_htc, reqobj, EVHTTP_REQ_POST, path) ) {
180
          debug("make request failed");
181
          evhttp_request_free(reqobj);
182
                evhttp_connection_free(local_htc);
183
          return UL_RETURN_FAIL;
184
        }
185
  event_base_dispatch(eventbase);
186
        //evhttp_connection_free(local_htc);
187
        return ret;
188
}
189
*/