Revision 59c85ad1

View differences:

event_http/Makefile
1
CFLAGS = -g -O0 -Wall
2

  
3
CPPFLAGS += -I../
4

  
5
all: event_http_server.o
6

  
7
clean:
8
	rm -f *.o
event_http/chunk_external_interface.h
1
/**
2
 * @file chunk_external_interface.h
3
 * 
4
 * Interface file for API to push chunks to external video players or pull from video sources.
5
 *
6
 * This is the interface for external chunk generators (i.e. video sources + a chunker)
7
 * or chunk consumers (i.e. an unchunker + video player) to push chunks into
8
 * a peer's internal chunk buffer, or to retrieve chunks from a peer's internal chunk buffer,
9
 * respectively.
10
 * The interface objects use a simple http channel to move chunks out/in of the
11
 * main peer's application, and use a pointer to the chunkbuffer and the necessary
12
 * callbacks.
13
 * This interface is built upon a libevent-based simple http client and server model
14
 * with no threads, thus it is based on callbacks and timer events, as required
15
 * by the current implementation of the peer application.
16
 *
17
 * Napa-Wine project 2009-2010
18
 * @author: Giuseppe Tropea <giuseppe.tropea@lightcomm.it>
19
 */
20

  
21
#ifndef _CHUNK_EXTERNAL_INTERFACE_H
22
#define _CHUNK_EXTERNAL_INTERFACE_H
23

  
24
#include <stdio.h>
25
//this depends on libevent for many reasons
26
#include <event-config.h>
27
#include <stdarg.h>
28
#include <sys/types.h>
29
#include <event2/util.h>
30
#include <event2/buffer.h>
31
#include <event2/http.h>
32
#include <event2/http_struct.h>
33
//thus i need a global variable with the external heartbeat and timings
34
extern struct event_base *eventbase;
35

  
36
//#include "../include/chunk.h"
37
//#include "../include/trade_msg_la.h"
38
//#include "../include/grapes_log.h"
39
#include <chunk.h>
40
//#include <trade_msg_la.h>
41
#include <grapes_log.h>
42

  
43
#include "ul_commons.h"
44

  
45
//moreover we are interfacing to the chunkbuffer
46
//we assume for now it is a global variable too
47
extern struct chunk_buffer *chunkbuffer;
48

  
49
/**
50
 * define a new data type for the pointer to a generic data_processor function
51
 */
52
typedef int (*data_processor_function)(const uint8_t *data, int data_len);
53

  
54

  
55
//DOCUMENTATION RELATIVE TO THE CHUNK_RECEIVER.C FILE
56
/**
57
 * Setup of a chunk receiver inside the peer.
58
 *
59
 * The chunk receiver receives chunks from an external application
60
 * via a regular http socket. The chunk receiver listens for chunks at
61
 * a specific address:port on the machine where the peer application
62
 * is running.
63
 * The chunk receiver uses for its internals a simple http server. When the
64
 * server receives a request, a callback is triggered to deal with
65
 * the incoming block of data (i.e. the incoming chunk).
66
 *
67
 * @param[in] address The IP address the receiver shall run at
68
 * @param[in] port The port the receiver shall listen at
69
 * @return 0 if OK, -1 if problems
70
 */
71
int ulChunkReceiverSetup(const char *address, unsigned short port);
72

  
73
/**
74
 * Callback for processing the received chunk.
75
 *
76
 * This function is called by the http server ProcessRequest function, which is
77
 * in turn triggered whenever a request with a data block is received.
78
 * This function receives from the internal http server the stripped block of bulk
79
 * data and interprets is as a chunk, pushing it into the peer's internal chunk buffer.
80
 *
81
 * @param[in] chunk The data to be processed (a chunk to be inserted into internal chunkbuffer)
82
 * @param[in] chunk_len The chunk length
83
 * @return 0 if OK, -1 if problems
84
 */
85
int ulPushChunkToChunkBuffer_cb(const uint8_t *encoded_chunk, int encoded_chunk_len);
86

  
87

  
88
//DOCUMENTATION RELATIVE TO THE EVENT_HTTP_SERVER.C FILE
89
/**
90
 * Sets up the internal http server.
91
 *
92
 * This function sets-up a libevent-based http server listening at a specific address:port.
93
 * When an http request is received by this server, the ProcessRequest callback is triggered,
94
 * which extracts the data embedded in the POST request, strips it and int turn gives it
95
 * to the specific data_processor function passed here in the setup operation.
96
 * Thus this http server is able to call a specific function to take care of
97
 * the received data, depending on who is setting it up.
98
 *
99
 * @param[in] address The IP address the server shall run at
100
 * @param[in] port The port the http server shall listen at
101
 * @param[in] data_processor The external function to call and pass the received data block to
102
 * @return -1 in case of error, when server does not get initialized, 0 if OK
103
 */
104
int ulEventHttpServerSetup(const char *address, unsigned short port, data_processor_function data_processor);
105

  
106
/**
107
 * Processes the received http request.
108
 *
109
 * Extract the bulk data buffer from the http POST request
110
 * and pass it to an external function for processing it specifically, by giving
111
 * a pointer to the data block and its length
112
 *
113
 * @param[in] req Contains info about the request, from libevent
114
 * @param[in] context A context for this request (an external data_processor function in this case)
115
 * @return -1 in case no data was extracted from the request (bad path, GET insted of POST, etc...), 0 if OK
116
 */
117
int ulEventHttpServerProcessRequest(struct evhttp_request *req, void *context);
118

  
119

  
120
//DOCUMENTATION RELATIVE TO THE CHUNK_SENDER.C FILE
121
/**
122
 * Send a chunk to all registered receivers.
123
 *
124
 * The chunk send is called whenever a fresh chunk is inserted into the
125
 * internal chunk buffer of the peer from the P2P network, in order to send
126
 * a copy of the fresh chunk out to external applications, as soon as
127
 * it gets into the peer.
128
 * Generally the fresh chunk is pushed to an external unchunking and video player
129
 * application, or a statistical or analysis application.
130
 * The chunk sender uses a simple regular http client writing to a socket
131
 * for its internal working.
132
 * This chunk sender is triggered via a callback activated by the internal chunk buffer
133
 * receiving a fresh chunk.
134
 * This chunk sender holds a static array of active connections to remote
135
 * applications, and initializes the connections at first time.
136
 *
137
 * @param[in] remote_address The IP address of the external application
138
 * @param[in] remote_port The port of the external application
139
 * @param[out] htc The pointer where the caller wants the connection to be stored
140
 * @return 0 if OK, -1 if problems
141
 */
142
int ulSendChunk(Chunk *c);
143

  
144
/**
145
 * Send out the chunk to an external application.
146
 *
147
 * This function is passed a chunk and sends it out to an external application via
148
 * the libevent's evhttp_connection object htc.
149
 * This function as of now is just a readability wrapper for the HttpClientPostData
150
 * function of the simple http client code.
151
 *
152
 * @param[in] c The chunk
153
 * @param[in] c_len The chunk length
154
 * @param[in] htc The pointer to the established connection with the external application
155
 * @param path The path within the remote application to push data to
156
 * @return 0 if OK, -1 if problems
157
 */
158
int ulPushChunkToRemoteApplication(Chunk *c, struct evhttp_connection *htc, const char *addr, const int port, const char *path);
159

  
160

  
161
//DOCUMENTATION RELATIVE TO THE EVENT_HTTP_CLIENT.C FILE
162
/**
163
 * Sets up a libevent-based http connection to a remote address:port
164
 *
165
 * This is the setup function to create an http socket from this peer to an external
166
 * application waiting for chunks on a specified address:port.
167
 * Pass a pointer to libevent's evhttp_connection object to this function
168
 * in order to get back an handler to the socket connection.
169
 *
170
 * @param[in] address The IP address of the remote http server to connect to
171
 * @param[in] port The port the remote http server is listening at
172
 * @param[out] htc The pointer to where the caller wants the connection pointer to be stored
173
 * @return -1 in case of error, when pointer to connection does not get initialized, 0 if OK
174
 */
175
int ulEventHttpClientSetup(const char *address, unsigned short port, struct evhttp_connection **htc);
176

  
177
/**
178
 * Post a block of data via http to a remote application.
179
 *
180
 * Performs a POST http request operation towards a remote http server in order to transfer a bulk
181
 * block of bytes to the server entity through the already establised connection.
182
 *
183
 * @param data A pointer to the block of bytes to be transferred
184
 * @param data_len The length of the data block
185
 * @param htc A pointer to the already established libevent-based http connection to the server
186
 * @param path The path within the remote application to push data to
187
 * @return -1 in case of error, or when pointer to connection does not get initialized, 0 if OK
188
 */
189
int ulEventHttpClientPostData(uint8_t *data, unsigned int data_len, struct evhttp_connection *htc, const char *addr, const int port, const char *path);
190

  
191

  
192
//DOCUMENTATION RELATIVE TO THE RECEIVERS_REGISTRY.C FILE
193
/**
194
 * Register a new receiver application.
195
 *
196
 * The remote application registers itself by declaring something
197
 * like "http://address:port/path/to/receiver/"
198
 * The function can be used to retrieve information about an already registered
199
 * application at a specific position, by giving NULL inputs except
200
 * for the pos parameter.
201
 *
202
 * @param[in,out] address The application IP address
203
 * @param[in,out] port The application port
204
 * @param[in,out] path The path where to send chunks
205
 * @param[in,out] pos The position in the registration array
206
 * @return 0 if OK, -1 if problems
207
 */
208
int ulRegisterApplication(char *address, int *port, char* path, int *pos);
209

  
210

  
211
#endif	/* CHUNK_EXTERNAL_INTERFACE_H */
event_http/chunk_receiver.c
1
/**
2
 * @file chunk_receiver.c
3
 *
4
 * Chunk Receiver "object".
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
 */
11

  
12
#include "chunk_external_interface.h"
13

  
14
int ulChunkReceiverSetup(const char *address, unsigned short port) {
15
  if(ulEventHttpServerSetup(address, port, &ulPushChunkToChunkBuffer_cb)) {
16
    return UL_RETURN_FAIL;
17
  }
18
  else {
19
    debug("Chunk receiver setup OK");
20
    return UL_RETURN_OK;
21
  }
22
}
23

  
24
int ulPushChunkToChunkBuffer_cb(const uint8_t *encoded_chunk, int encoded_chunk_len) {
25
  Chunk decoded_chunk;
26
  debug("Processing incoming chunk of %d encoded bytes", encoded_chunk_len);
27
//print_block(encoded_chunk, encoded_chunk_len);
28
  int size = decodeChunk(&decoded_chunk, encoded_chunk, encoded_chunk_len);
29
  debug("Just decoded chunk %d", decoded_chunk.id);
30
  //push new chunk into chunk buffer
31
  chbAddChunk(chunkbuffer, &decoded_chunk);
32
  debug("Just pushed chunk %d of %d bytes into chunkbuf", decoded_chunk.id, size);
33
  return UL_RETURN_OK;
34
}
35

  
36
void print_block(const uint8_t *b, int size) {
37
int i=0;
38
printf("BEGIN OF %d BYTES---\n", size);
39
for(i=0; i<size; i++) {
40
printf("%d ", *(b+i));
41
}
42
printf("END OF %d BYTES---\n", size);
43
}
event_http/chunk_sender.c
1
/**
2
 * @file chunk_sender.c
3
 *
4
 * Chunk Sender "object".
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
 */
11

  
12
#include <string.h>
13

  
14
#include "chunk_external_interface.h"
15
#include "ul_commons.h"
16

  
17
//this definition should seat in a central place...
18
#define UL_ENCODED_CHUNK_HEADER_SIZE 20
19

  
20
int ulSendChunk(Chunk *c) {
21
  //they will be NULL just the first time
22
  static struct evhttp_connection *htc[UL_MAX_EXTERNAL_APPLICATIONS]; //initialized to NULL by compiler
23
  char addr[UL_IP_ADDRESS_SIZE] = "";
24
  int port = 0;
25
  char path[UL_PATH_SIZE] = "";
26
  int i = 0;
27
  //the code in this function cycles through all registered applications,
28
  //so the return code should be an "OR" of the singular return values...
29
  int ret = 0;
30

  
31
  for(i=0; i<UL_MAX_EXTERNAL_APPLICATIONS; i++) {
32
    addr[0] = '\0';
33
    port = 0;
34
    path[0] = '\0';
35

  
36
    //check whether we have a registered application at position i
37
    if(ulRegisterApplication(addr, &port, path, &i) == UL_RETURN_FAIL) {
38
      //some problem occurred
39
      error("ulSendChunk unable to check connection at position %d", i);
40
      ret = UL_RETURN_FAIL;
41
    }
42
    else {
43
      //lets check if the RegisterApplication has given back an address for the empty slot
44
      if(strlen(addr)) {
45
/*
46
        if(htc[i] == NULL) { //we have an address but not a connection yet
47
          //setup a new connection with the newly registered application and put it in position i
48
          if(ulEventHttpClientSetup(addr, port, &htc[i]) == UL_RETURN_FAIL) {
49
            error("ulSendChunk unable to setup a connection to %s:%d at position %d", addr, port, i);
50
            ret = UL_RETURN_FAIL;
51
          }
52
        }
53
*/
54
        //push the chunk
55
        if(ulPushChunkToRemoteApplication(c, htc[i], addr, port, path)) {
56
          error("ulSendChunk unable to push chunk to application %s:%d%s through connection at position %d", addr, port, path, i);
57
          ret = UL_RETURN_FAIL;
58
        }
59
        else {
60
          //debug("ulSendChunk pushed chunk to application %s:%d%s through connection at position %d", addr, port, path, i);
61
          ret = UL_RETURN_OK;
62
        }
63
      }
64
      else {
65
        debug("ulSendChunk no application seems to be registered at position %d", i);
66
      }
67
    } //application registry check ok
68
  } //cycle all positions
69
  return ret;
70
}
71

  
72
int ulPushChunkToRemoteApplication(Chunk *c, struct evhttp_connection *htc, const char *addr, const int port, const char *path) {
73
  int encoded_chunk_size = 0;
74
  uint8_t *buff = NULL;
75
  int size = 0;
76
  int ret = 0;
77

  
78
  //encode the chunk into a bitstream
79
  encoded_chunk_size = UL_ENCODED_CHUNK_HEADER_SIZE + c->size + c->attributes_size;
80
  if( (buff=(uint8_t *)malloc(encoded_chunk_size)) == NULL ) {
81
    error("memory allocation failed in encoding chunk to push via http");
82
    return UL_RETURN_FAIL;
83
  }
84
  size = encodeChunk(c, buff, encoded_chunk_size);
85

  
86
  if(size > 0) {
87
    ret = ulEventHttpClientPostData(buff, size, htc, addr, port, path);
88
    debug("Just HTTP pushed chunk %d of %d bytes encoded into %d bytes. Ret value of %d", c->id, c->size, size, ret);
89
    free(buff);
90
    return UL_RETURN_OK;
91
  }
92
  else {
93
    warn("size zero in a encode chunk!!!!");
94
    free(buff);
95
    return UL_RETURN_FAIL;
96
  }
97
}
event_http/event_http_client.c
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
*/
event_http/event_http_server.c
1
/**
2
 * @file event_http_server.c
3
 *
4
 * Simple http server for internal use.
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 <string.h>
14

  
15
#include <http_default_urls.h>
16
#include "chunk_external_interface.h"
17

  
18
int ulEventHttpServerSetup(const char *address, unsigned short port, data_processor_function data_processor) {
19
  struct evhttp* evh = NULL;
20
  debug("Setting up event-based http server listening at %s:%d", address, port);
21

  
22
  evh = evhttp_new(eventbase);
23

  
24
  if(evh != NULL) {
25
    info("Event-based http server at %s:%d has been setup", address, port);
26
    fprintf(stderr, "Event-based http server at %s:%d has been setup\n", address, port);
27
  }
28
  else {
29
    error("Setup of event-based http server at %s:%d FAILED", address, port);
30
    return UL_RETURN_FAIL;
31
  }
32

  
33
  if(evhttp_bind_socket(evh, address, port) != -1) {
34
    info("Event-based http server socket bind with %s:%d OK", address, port);
35
  }
36
  else {
37
    error("Bind of event-based http server with %s:%d FAILED", address, port);
38
    return UL_RETURN_FAIL;
39
  }
40

  
41
  //when a request for a generic path comes to the server, trigger the ulEventHttpServerProcessRequest
42
  //function and also pass to it a pointer to an external data_processor function, which is
43
  //able to handle the received data specifically
44
  evhttp_set_gencb(evh, ulEventHttpServerProcessRequest, data_processor);
45
  return UL_RETURN_OK;
46
}
47

  
48
int ulEventHttpServerProcessRequest(struct evhttp_request *req, void *context) {
49
  struct evbuffer* input_buffer;
50
  const uint8_t *data;
51
  int data_len;
52
  char *path = req->uri;
53
  int ret;
54

  
55
  //cast the context as it is a data_processor_function
56
  data_processor_function data_processor = (data_processor_function)context;
57

  
58
  debug("HTTP request received for %s of type %d", req->uri, req->type);
59
  input_buffer = evhttp_request_get_input_buffer(req);
60
  data_len = evbuffer_get_length(input_buffer);
61
  if(req->type == EVHTTP_REQ_POST) {
62
    //extract the path of request
63
    if(!strncmp(path, UL_HTTP_PREFIX , strlen(UL_HTTP_PREFIX))) {  //if it begins by "http://"
64
      path = strchr(path + strlen(UL_HTTP_PREFIX),'/'); //skip "http://host:port" part
65
    }
66
    debug("HTTP POST request is for path %s", path);
67
    fprintf(stderr, "HTTP POST request is for path %s\n	", path);
68

  
69
    if(!strcmp(path, UL_DEFAULT_CHUNKBUFFER_PATH)) {
70
      //give back the data
71
      //should i copy it in order to "free" the req pointer??
72
      //no, because the data processr makes a copy
73
      //data = (uint8_t*)req->input_buffer;
74
      data = (const uint8_t *)evbuffer_pullup(input_buffer, data_len);
75
 
76
      //sending a reply to the client
77
      evhttp_send_reply(req, 200, "OK", NULL);
78
      //debug("HTTP REPLY OK");
79
      if(context != NULL) {
80
        //invoke the data_processor function, which returns -1 and 0 as well depending on outcome
81
        debug("HTTP server invoking the data processor");
82
        ret = (*data_processor)(data, data_len);
83
      }
84
      else {
85
        debug("HTTP server NOT invoking the data processor: NULL");
86
        ret = UL_RETURN_OK;
87
      }
88
    }
89
    else {
90
      evhttp_send_reply(req, 400, "BAD URI", NULL);
91
      error("HTTP REPLY BAD URI ");
92
      ret = UL_RETURN_FAIL;
93
    }
94
  }
95
  else if(req->type == EVHTTP_REQ_GET || req->type == EVHTTP_REQ_PUT) {
96
    error("Received GET or PUT HTTP request");
97
    evhttp_send_reply(req, 404, "NOT FOUND", NULL);
98
    ret = UL_RETURN_FAIL;
99
  }
100
  else {
101
    error("HTTP Unknown request");
102
    evhttp_send_reply(req, 404, "NOT FOUND", NULL);
103
    ret = UL_RETURN_FAIL;
104
  }
105
  //evbuffer_free(input_buffer);
106
  //evhttp_request_free(req);
107
  return ret;
108
}
event_http/receivers_registry.c
1
/**
2
 * @file receiver_registry.c
3
 *
4
 * A registry of external applications willing to receive chunks.
5
 *
6
 * Based on a static array of information about registered applications.
7
 *
8
 * Napa-Wine project 2009-2010
9
 * @author: Giuseppe Tropea <giuseppe.tropea@lightcomm.it>
10
 */
11

  
12
#include "chunk_external_interface.h"
13
#include "ul_commons.h"
14

  
15
int ulRegisterApplication(char *address, int *port, char* path, int *pos) {
16
  //the following hopefully initializes all alements of the array with the same values...
17
  static ApplicationInfo apps[UL_MAX_EXTERNAL_APPLICATIONS] = {
18
    {"", 0, "", 0} //address, port, path, status
19
  };
20

  
21
  if(*pos >= UL_MAX_EXTERNAL_APPLICATIONS) {
22
    error("Registering application index > MAX error");
23
    return UL_RETURN_FAIL;
24
  }
25
  if(address[0] == '\0' && *port == 0 && path[0] == '\0') { //caller wants to retrieve status of application
26
    //give back the values of the application at position pos
27
    sprintf(address, "%s", apps[*pos].address);
28
    *port = apps[*pos].port;
29
    sprintf(path, "%s", apps[*pos].path);
30
    //debug("Somebody asked for the status of application at %s:%d%s, position %d", address, *port, path, *pos);
31
    return UL_RETURN_OK;
32
  }
33
  else { //register an application at the first free position
34
    //FIND A FREE INDEX
35
    int free_index = 1; //just to try, skipping position zero...
36
    //REGISTER BY FILLING INFO
37
    sprintf(apps[free_index].address, "%s", address);
38
    apps[free_index].port = *port;
39
    sprintf(apps[free_index].path, "%s", path);
40
    //give back the registered info
41
    *pos = free_index;
42
    info("Somebody registered an external application at %s:%d%s, position %d", address, *port, path, *pos);
43

  
44
    return UL_RETURN_OK;
45
  }
46
}
event_http/ul_commons.h
1
#ifndef _UL_COMMONS_H
2
#define _UL_COMMONS_H
3

  
4

  
5
#define UL_RETURN_OK 0
6
#define UL_RETURN_FAIL -1
7
#define UL_IP_ADDRESS_SIZE 20
8
#define UL_PATH_SIZE 128
9
#define UL_URL_SIZE 256
10
#define UL_MAX_EXTERNAL_APPLICATIONS 5
11

  
12
/**
13
 * define a new data type for the aggregated info about an application registering itself as chunk receiver
14
 */
15
typedef struct {
16
  char address[UL_IP_ADDRESS_SIZE];
17
  int port;
18
  char path[UL_PATH_SIZE];
19
  int status;
20
} ApplicationInfo;
21

  
22
/**
23
 * commodity function to print a block of bytes
24
 */
25
void print_block(const uint8_t *b, int size);
26

  
27

  
28
#endif
event_http/ul_init.c
1
/**
2
 * @file ul_init.c
3
 *
4
 * Initialization call for the UserLayer module.
5
 *
6
 * Napa-Wine project 2009-2010
7
 * @author: Giuseppe Tropea <giuseppe.tropea@lightcomm.it>
8
 */
9

  
10
#include "chunk_external_interface.h"
11

  
12
//register the player in the list of registered chunk receivers
13
//register the ulNewChunkArrived into the chunkbuffer's RegisterNotifier callback
14

  
15
//fill the global pointer to the chunk_buffer
16
cb = NULL;

Also available in: Unified diff