00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <sys/types.h>
00025 #include <stdlib.h>
00026 #include <stdio.h>
00027 #include <string.h>
00028 #include <unistd.h>
00029 #include <fcntl.h>
00030 #include <errno.h>
00031 #include <sys/time.h>
00032 #include <sys/socket.h>
00033 #include <netinet/in.h>
00034 #include <arpa/inet.h>
00035
00036 #include "event.h"
00037 #include "str.h"
00038 #include "rtp.h"
00039 #include "rtsp.h"
00040
00041 #undef DEBUG
00042
00043 struct param *_param;
00044
00045 struct session {
00046 struct session *next;
00047 struct session *prev;
00048 char id[32];
00049 };
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060 #define CONN_STATE_START 0
00061 #define CONN_STATE_RTSP 1
00062 #define CONN_STATE_RTSP_REQ 2
00063 #define CONN_STATE_INTERLEAVED 3
00064 #define CONN_STATE_HTTP 10
00065
00066 struct conn {
00067 struct conn *next;
00068 struct conn *prev;
00069 int fd;
00070 struct sockaddr_in client_addr;
00071 struct event *read_event;
00072 struct event *write_event;
00073 int state;
00074 char req_buf[4096];
00075 int req_len;
00076 struct { char *name; char *value; } req_hdr[16];
00077 unsigned char send_buf[65536];
00078 int send_buf_r;
00079 int send_buf_w;
00080 int drop_after;
00081 int close_flag;
00082 struct session *attached_session;
00083 };
00084
00085 struct listener {
00086 int fd;
00087 };
00088
00089 struct conn *conn_list = NULL;
00090 struct session *sess_list = NULL;
00091
00092 static void do_read( struct event *e, void *d );
00093
00094 static void del_session( struct session *sess )
00095 {
00096 if( sess->next ) sess->next->prev = sess->prev;
00097 if( sess->prev ) sess->prev->next = sess->next;
00098 else sess_list = sess->next;
00099 free( sess );
00100 }
00101
00102 static struct session *new_session( void )
00103 {
00104 struct session *sess;
00105 int len;
00106
00107 sess = (struct session *)malloc( sizeof( struct session ) );
00108 sess->next = sess_list;
00109 sess->prev = NULL;
00110 if( sess->next ) sess->next->prev = sess;
00111 sess_list = sess;
00112
00113 for( len = 0; len < 15; ++len )
00114 sprintf( sess->id + len * 2, "%02X",
00115 (unsigned int)( random() & 0xff ) );
00116 sess->id[30] = 0;
00117 return sess;
00118 }
00119
00120 static struct session *get_session( char *id )
00121 {
00122 struct session *s;
00123
00124 for( s = sess_list; s; s = s->next )
00125 if( ! strcmp( s->id, id ) ) break;
00126 return s;
00127 }
00128
00129 static void close_session( struct session *s )
00130 {
00131 del_session( s );
00132 }
00133
00134 static void drop_conn(struct conn *c) {
00135 if(c->attached_session)
00136 close_session(c->attached_session);
00137 remove_event(c->read_event);
00138 remove_event(c->write_event);
00139 if(c->fd >= 0)
00140 close(c->fd);
00141 c->fd = -1;
00142 if(c->next)
00143 c->next->prev = c->prev;
00144 if(c->prev)
00145 c->prev->next = c->next;
00146 else
00147 conn_list = c->next;
00148 free(c);
00149 }
00150
00151 static void conn_write( struct event *e, void *d )
00152 {
00153 struct conn *c = (struct conn *)d;
00154 int ret, len;
00155
00156 while( c->send_buf_r != c->send_buf_w )
00157 {
00158 if( c->send_buf_w < c->send_buf_r )
00159 len = sizeof( c->send_buf ) - c->send_buf_r;
00160 else
00161 len = c->send_buf_w - c->send_buf_r;
00162 ret = write( c->fd, c->send_buf + c->send_buf_r, len );
00163 if( ret <= 0 )
00164 {
00165 if( ret < 0 && errno == EAGAIN ) return;
00166 drop_conn( c );
00167 return;
00168 }
00169 c->send_buf_r += ret;
00170 if( c->send_buf_r == sizeof( c->send_buf ) )
00171 c->send_buf_r = 0;
00172 }
00173 if( c->drop_after ) drop_conn( c );
00174 else set_event_enabled( c->write_event, 0 );
00175 }
00176
00177 static inline int avail_send_buf( struct conn *c )
00178 {
00179 if( c->send_buf_r > c->send_buf_w )
00180 return c->send_buf_r - c->send_buf_w - 1;
00181 else return sizeof( c->send_buf ) - c->send_buf_w + c->send_buf_r - 1;
00182 }
00183
00184 static int send_data( struct conn *c, unsigned char *d, int len )
00185 {
00186 if( avail_send_buf( c ) < len ) return 1;
00187
00188 while( --len >= 0 )
00189 {
00190 c->send_buf[c->send_buf_w++] = *(d++);
00191 if( c->send_buf_w == sizeof( c->send_buf ) )
00192 c->send_buf_w = 0;
00193 }
00194
00195 set_event_enabled( c->write_event, 1 );
00196
00197 return 0;
00198 }
00199
00200
00201 static char *get_header( struct conn *c, char *name )
00202 {
00203 int i;
00204 static char *empty = "";
00205
00206 for( i = 0; c->req_hdr[i].name; ++i )
00207 if( ! strcasecmp( c->req_hdr[i].name, name ) )
00208 return c->req_hdr[i].value;
00209 return empty;
00210 }
00211
00212 static int handle_OPTIONS( struct conn *c )
00213 {
00214 unsigned char rep[8192];
00215
00216 send_data( c, rep, sprintf( rep, "RTSP/1.0 200 OK\r\nCSeq: %s\r\nPublic: DESCRIBE, SETUP, TEARDOWN, PLAY\r\n\r\n", get_header( c, "CSeq" ) ) );
00217 return 0;
00218 }
00219
00220 static int handle_DESCRIBE( struct conn *c )
00221 {
00222 char rep[8192], sdp[8192];
00223 int rep_len;
00224
00225 if((_param->rtsp_use_cmd_addr && !ismulticast(_param) && str_count) ||
00226 (!_param->rtsp_use_cmd_addr && str_count)){
00227 c->close_flag = 1;
00228 send_data( c, rep, sprintf( rep, "RTSP/1.0 455 Server is busy\r\nCSeq: %s\r\n\r\n", get_header( c, "CSeq" ) ) );
00229 return 0;
00230 }
00231
00232 write_sdp(_param, 0, sdp);
00233 rep_len = sprintf( rep,
00234 "RTSP/1.0 200 OK\r\nCSeq: %s\r\n"
00235 "Content-Type: application/sdp\r\nContent-Length: %d\r\n\r\n",
00236 get_header( c, "CSeq" ), strlen(sdp));
00237 #ifdef DEBUG
00238 fprintf(stderr, "DESCRIBE reply:\n%s", rep);
00239 fprintf(stderr, "%s", sdp);
00240 #endif
00241 send_data( c, rep, rep_len );
00242 send_data( c, sdp, strlen(sdp) );
00243 return 0;
00244 }
00245
00246 static int rtsp_udp_setup( struct conn *c, char *t )
00247 {
00248 char *p, *end;
00249 int cport;
00250 struct session *s;
00251 unsigned char rep[8192];
00252 char mode_u[] = "unicast", mode_m[] = "multicast", *mode;
00253
00254 memset(rep, 0, 8192);
00255
00256 if( ! ( p = strstr( t, "client_port" ) ) || *(p + 11) != '=' )
00257 return -1;
00258 cport = strtol( p + 12, &end, 10 );
00259 if( end == p + 12 ) return -1;
00260
00261 fprintf(stderr, "t == |%s|\r\n", t);
00262
00263 #ifdef DEBUG
00264 fprintf(stderr, "client port is %d\n", cport);
00265 #endif
00266 s = new_session();
00267
00268 if((mode = strstr( t, "multicast" ))){
00269 mode = mode_m;
00270 } else {
00271 mode = mode_u;
00272 }
00273
00274 if(!_param->rtsp_use_cmd_port){
00275 if(str_count<1){
00276 _param->dport = cport;
00277 }
00278 }
00279
00280 if(!_param->rtsp_use_cmd_addr){
00281 if(str_count<1){
00282 _param->dst = strdup(inet_ntoa(c->client_addr.sin_addr));
00283 }
00284 }
00285
00286 if(!str_count++) str_setup = 1;
00287 usleep(10);
00288
00289 c->attached_session = s;
00290 sprintf( rep, "RTSP/1.0 200 OK\r\nCSeq: %s\r\n"
00291 "Session: %s\r\nTransport: RTP/AVP;"
00292 "%s;destination=%s;port=%d\r\n\r\n",
00293 get_header( c, "CSeq" ), s->id, mode, _param->dst, cport);
00294 #ifdef DEBUG
00295 fprintf(stderr, "SETUP reply:\n%s", rep);
00296 #endif
00297 send_data( c, rep, strlen(rep) );
00298
00299 return 0;
00300 }
00301
00302 static int handle_SETUP( struct conn *c )
00303 {
00304 char *t;
00305 unsigned char rep[8192];
00306
00307 memset(rep, 0, 8192);
00308
00309 t = get_header( c, "Transport" );
00310
00311 if( ( ! strncasecmp( t, "RTP/AVP", 7 ) && t[7] != '/' ) ||
00312 ! strncasecmp( t, "RTP/AVP/UDP", 11 ) )
00313 {
00314 if( rtsp_udp_setup( c, t ) == 0 ) return 0;
00315 }
00316
00317 send_data( c, rep, sprintf( rep, "RTSP/1.0 461 Unsupported Transport\r\nCSeq: %s\r\n\r\n", get_header( c, "CSeq" ) ) );
00318
00319 return 0;
00320 }
00321
00322 static int handle_PLAY( struct conn *c )
00323 {
00324 struct session *s;
00325 unsigned char rep[8192];
00326
00327 memset(rep, 0, 8192);
00328
00329 if( ! ( s = get_session( get_header( c, "Session" ) ) ) )
00330 {
00331 send_data( c, rep, sprintf( rep, "RTSP/1.0 454 Session Not Found\r\nCSeq: %s\r\n\r\n", get_header( c, "CSeq" ) ) );
00332 return 0;
00333 }
00334
00335
00336 sprintf( rep, "RTSP/1.0 200 OK\r\nCSeq: %s\r\nSession: %s"
00337 "\r\n\r\n",
00338 get_header( c, "CSeq" ), s->id );
00339 #ifdef DEBUG
00340 fprintf(stderr, "PLAY reply:\n%s", rep);
00341 #endif
00342 send_data( c, rep, strlen(rep) );
00343 str_play = 1;
00344
00345 return 0;
00346 }
00347
00348 static int handle_PAUSE( struct conn *c )
00349 {
00350 struct session *s;
00351 unsigned char rep[8192];
00352
00353 memset(rep, 0, 8192);
00354
00355 if( ! ( s = get_session( get_header( c, "Session" ) ) ) )
00356 {
00357 send_data( c, rep, sprintf( rep, "RTSP/1.0 454 Session Not Found\r\nCSeq: %s\r\n\r\n", get_header( c, "CSeq" ) ) );
00358 return 0;
00359 }
00360
00361
00362 sprintf( rep, "RTSP/1.0 200 OK\r\nCSeq: %s\r\nSession: %s"
00363 "\r\n\r\n",
00364 get_header( c, "CSeq" ), s->id );
00365 #ifdef DEBUG
00366 fprintf(stderr, "PAUSE reply:\n%s", rep);
00367 #endif
00368 send_data( c, rep, strlen(rep) );
00369 if(str_count<2){
00370 if(!_param->rtsp_qt_compat){
00371 str_play = 0;
00372 }
00373 }
00374
00375 return 0;
00376 }
00377
00378
00379 static int handle_TEARDOWN( struct conn *c )
00380 {
00381 struct session *s;
00382 unsigned char rep[8192];
00383
00384 if( ! ( s = get_session( get_header( c, "Session" ) ) ) )
00385 {
00386 send_data( c, rep, sprintf( rep, "RTSP/1.0 454 Session Not Found\r\nCSeq: %s\r\n\r\n", get_header( c, "CSeq" ) ) );
00387 return 0;
00388 }
00389 send_data( c, rep, sprintf( rep, "RTSP/1.0 200 OK\r\nCSeq: %s\r\nSession: %s\r\n\r\n", get_header( c, "CSeq" ), s->id ) );
00390 if( c->attached_session == s ) c->attached_session = NULL;
00391 close_session( s );
00392
00393 if(--str_count<=0){
00394 str_count = 0;
00395 if(!_param->rtsp_qt_compat){
00396 str_teardown = 1;
00397 }
00398 }
00399 c->close_flag = 1;
00400 return 0;
00401 }
00402
00403 static int handle_unknown( struct conn *c )
00404 {
00405 unsigned char rep[8192];
00406
00407 send_data( c, rep, sprintf( rep, "RTSP/1.0 501 Not Implemented\r\nCSeq: %s\r\n\r\n", get_header( c, "CSeq" ) ) );
00408 return 0;
00409 }
00410
00411 static int handle_request( struct conn *c )
00412 {
00413 char *t;
00414 int i = 0;
00415
00416 if( c->req_buf[0] == 0 ) return -1;
00417
00418 #ifdef DEBUG
00419 fprintf(stderr, "Request:\n%s\n", c->req_buf);
00420 #endif
00421
00422
00423 for( t = c->req_buf; *t != '\r' && *t != '\n'; ++t )
00424 if( *t == 0 ) return -1;
00425 *(t++) = 0;
00426 if( *t == '\n' ) *(t++) = 0;
00427
00428 for( i = 0; i < 15; ++i )
00429 {
00430
00431 c->req_hdr[i].name = t;
00432
00433 for( ; *t != ':'; ++t )
00434 if( *t == 0 || *t == '\r' || *t == '\n' ) return -1;
00435 *(t++) = 0;
00436
00437 for( ; *t == ' '; ++t )
00438 if( *t == 0 ) return -1;
00439
00440 c->req_hdr[i].value = t;
00441 for( ; *t != '\r' && *t != '\n'; ++t )
00442 if( *t == 0 ) return -1;
00443
00444 *(t++) = 0;
00445 if( *t == '\n' ) *(t++) = 0;
00446
00447 if( *t == 0 || *t == '\r' || *t == '\n' ) break;
00448 }
00449 if( i == 15 ) return -1;
00450 c->req_hdr[i + 1].name = NULL;
00451
00452 #if 0
00453 for( i = 0; i < 16 && c->req_hdr[i].name; ++i )
00454 {
00455 printf( "Header name = %s\n", c->req_hdr[i].name );
00456 printf( "Header value = %s\n", c->req_hdr[i].value );
00457 }
00458 #endif
00459
00460 if( ! strncasecmp( c->req_buf, "OPTIONS ", 8 ) )
00461 return handle_OPTIONS( c );
00462 else if( ! strncasecmp( c->req_buf, "DESCRIBE ", 9 ) )
00463 return handle_DESCRIBE( c );
00464 else if( ! strncasecmp( c->req_buf, "SETUP ", 6 ) )
00465 return handle_SETUP( c );
00466 else if( ! strncasecmp( c->req_buf, "PLAY ", 5 ) )
00467 return handle_PLAY( c );
00468 else if( ! strncasecmp( c->req_buf, "PAUSE ", 6 ) )
00469 return handle_PAUSE( c );
00470 else if( ! strncasecmp( c->req_buf, "TEARDOWN ", 9 ) )
00471 return handle_TEARDOWN( c );
00472 else return handle_unknown( c );
00473 }
00474
00475 static int parse_client_data( struct conn *c )
00476 {
00477 char *t;
00478
00479 switch( c->state )
00480 {
00481 case CONN_STATE_START:
00482 if( strchr( c->req_buf, '\n' ) )
00483 {
00484 c->state = CONN_STATE_RTSP;
00485 return 1;
00486 }
00487 break;
00488 case CONN_STATE_RTSP:
00489 if( c->req_len < 4 ) return 0;
00490 c->state = CONN_STATE_RTSP_REQ;
00491 return 1;
00492 case CONN_STATE_RTSP_REQ:
00493 if( ! ( t = strstr( c->req_buf, "\r\n\r\n" ) ) ) return 0;
00494 t[2] = 0;
00495 if( handle_request( c ) < 0 ) return -1;
00496
00497
00498 c->req_len = 0;
00499 if( c->state == CONN_STATE_RTSP_REQ )
00500 c->state = CONN_STATE_RTSP;
00501 break;
00502 }
00503 return 0;
00504 }
00505
00506 static void do_read( struct event *e, void *d )
00507 {
00508 struct conn *c = (struct conn *)d;
00509 int ret;
00510
00511 for(;;)
00512 {
00513 ret = read( c->fd,
00514 c->req_buf + c->req_len,
00515 sizeof( c->req_buf ) - c->req_len - 1 );
00516 if( ret <= 0 )
00517 {
00518 if( ret < 0 )
00519 {
00520 if( errno == EAGAIN ) return;
00521 fprintf( stderr, "read error%s: %s\n",
00522 "",
00523 strerror( errno ) );
00524 } else{
00525 #ifdef DEBUG
00526 fprintf( stderr, "connection closed\n" );
00527 #endif
00528 }
00529
00530 if(!c->close_flag){
00531 str_count--;
00532 }
00533 if(str_count<=0){
00534 str_count = 0;
00535 if(!_param->rtsp_qt_compat){
00536 str_teardown = 1;
00537 }
00538 }
00539 drop_conn( c );
00540 return;
00541 }
00542
00543 c->req_len += ret;
00544
00545 if( c->req_len == sizeof( c->req_buf ) - 1 )
00546 {
00547 fprintf( stderr, "malformed request from client\n" );
00548 drop_conn( c );
00549 return;
00550 }
00551
00552 c->req_buf[c->req_len] = 0;
00553 while( ( ret = parse_client_data( c ) ) > 0 );
00554 if( ret < 0 ) return;
00555 }
00556 }
00557
00558 static void do_accept(struct event *e, void *d) {
00559 struct listener *listener = (struct listener *)d;
00560 int fd;
00561 socklen_t addrlen;
00562 struct sockaddr_in addr;
00563 struct conn *c;
00564
00565 addrlen = sizeof(addr);
00566 if((fd = accept( listener->fd, (struct sockaddr *)&addr, &addrlen)) < 0) {
00567 perror("accept");
00568 exit(1);
00569 }
00570
00571 #ifdef DEBUG
00572 fprintf(stderr, "accepted connection\n");
00573 #endif
00574
00575 fcntl(fd, F_SETFL, O_NONBLOCK);
00576
00577 c = (struct conn *)malloc(sizeof(struct conn));
00578 c->next = conn_list;
00579 if(c->next)
00580 c->next->prev = c;
00581 c->prev = NULL;
00582 c->fd = fd;
00583 c->client_addr = addr;
00584 c->state = CONN_STATE_START;
00585 c->req_len = 0;
00586 c->read_event = add_fd_event(fd, 0, 0, do_read, c);
00587 c->write_event = add_fd_event(fd, 1, 0, conn_write, c);
00588 set_event_enabled(c->write_event, 0);
00589 c->send_buf_r = c->send_buf_w = 0;
00590 c->drop_after = 0;
00591 c->attached_session = NULL;
00592 conn_list = c;
00593 c->close_flag = 0;
00594 }
00595
00596
00597
00598 int rtsp_listen(struct param *p) {
00599 int port;
00600 struct sockaddr_in addr;
00601 struct listener *listener;
00602 int opt, fd;
00603
00604 _param = p;
00605 port = p->rtsp_port;
00606
00607 addr.sin_family = AF_INET;
00608 addr.sin_addr.s_addr = 0;
00609 addr.sin_port = htons(port);
00610
00611 if((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0) {
00612 perror("socket");
00613 return -1;
00614 }
00615 opt = 1;
00616 if(setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
00617 perror("setsockopt");
00618 if(bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
00619 perror("bind");
00620 close(fd);
00621 return -1;
00622 }
00623 if(listen(fd, 5) < 0) {
00624 perror("listen");
00625 close(fd);
00626 return -1;
00627 }
00628
00629 listener = (struct listener *)malloc(sizeof(struct listener));
00630 listener->fd = fd;
00631
00632 add_fd_event(fd, 0, 0, do_accept, listener);
00633 #ifdef DEBUG
00634 fprintf(stderr, "listening on port %d\n", port);
00635 #endif
00636 return 0;
00637 }
00638