/* * Function Name: http_request * * Parameters: char *in_URL http URL to request * int in_Method enum for method type * (see http.h) * Description: handle a request to an http server. this is being kept * simple for a purpose, call the function with an http URL * and have return the response inside HTTP_Response. * * Returns: HTTP_Response struct * * NOTE: the memory is allocated for the data transfered, * and it is the responsibility of the *CALLER* to free * the memory. it's very easy to accumulate several * megabytes of data. * */ HTTP_Response http_request( char *in_URL, HTTP_Extra *in_Extra, HTTP_Method in_Method, unsigned long in_Flags ) { char *pBuf; char *pRequest; char *path; char scheme[50], host[MAXPATHLEN]; char *pData, *pBase, *pHCode, *pHMsgEnd; // *pScheme, *pHost, *pPath, char szContent[32]; char *proxy; int port; struct hostent *nameinfo; int s; struct sockaddr_in addr; unsigned long total_bytes, bytes, header_size = 0UL, data_size = 0UL, alloc_size = 0UL; fd_set set; int in_header; char *h_end_ptr; #ifdef DEBUG struct timeval from_request, from_reply, end; long secs, usecs, bytes_per_sec; #endif HTTP_Response hResponse = { 0,0,0,0,0,"","" }; #ifdef HF_DO_FILE // CRH It's a file or directory if(in_Method == kHMethodGet && !strncasecmp(in_URL, "file://", 7)) return do_file( in_URL ); #endif /* HF_DO_FILE */ memset( hResponse.szHCode, '\0', HCODESIZE ); memset( hResponse.szHMsg, '\0', HMSGSIZE ); memset( host, '\0', MAXPATHLEN ); memset( scheme, '\0', 50 ); memset( szContent, '\0', 32 ); // the GET and POST as of 9/4/2001 /* The URL is limited to 8k in all cases. * For GET request with many/big arguments, this may be a problem, but * with that much data you should be using a POST. * For POST request, the arguments are in in_Extra->PostData, which is * not limited, so it should always be fine. * Jean II */ if( strlen( in_URL ) < GETLEN ) // compare against max request { // allocate the size of the URL // add 1024 bytes for the header pRequest = (char *)calloc( 1, strlen( in_URL ) + 1024 ); if( pRequest == NULL ) { hResponse.iError = errno; hResponse.pError = strerror( errno ); return( hResponse ); } } else { debug( stderr, "*** Request too large, truncating to 8192 max size\n*** will try request anyway...\n" ); in_URL[GETLEN] = '\0'; pRequest = (char *)calloc( 1, GETLEN + 1024 ); if( pRequest == NULL ) { hResponse.iError = errno; hResponse.pError = strerror( errno ); return( hResponse ); } } // the http_proxy environment setting is common use for a proxy server, // and the way it was setup per httpget. if( (in_Flags & HFLAG_FORCE_NO_PROXY) || ((proxy = getenv( "http_proxy" )) == NULL ) ) { /* MAR-18-2003 path may be NULL now, take this into account */ path = parse_url( in_URL, scheme, host, &port ); if ( !path ) { hResponse.iError = errno; hResponse.pError = strerror( errno ); if( pRequest ) free( pRequest ); return( hResponse ); } debug( stderr, "URL scheme = %s\n", scheme ); debug( stderr, "URL host = %s\n", host ); debug( stderr, "URL port = %d\n", port ); debug( stderr, "URL path = %s\n", path ); // check for http scheme to be safe. if( strcasecmp(scheme, "http") != 0 ) { fprintf( stderr, "http_request cannot operate on %s URLs without a proxy\n", scheme ); if( path ) free( path ); if( pRequest ) free( pRequest ); return( hResponse ); } } else { path = parse_url( proxy, scheme, host, &port ); if( path ) free( path ); // free it, in_URL will be assigned to it debug( stderr, "Using proxy server at %s:%d\n", host, port ); /* MAR 18-2003 jjsa: path will be freed later, alloc memory ! */ path = strdup(in_URL); if( path == NULL ) { if( pRequest ) free( pRequest ); return( hResponse ); } } /* -- Note : -- * After this point, in_URL is no longer used and you should only * use "path". - Jean II */ /* Find out the IP address */ if( (nameinfo = gethostbyname( host )) == NULL ) { addr.sin_addr.s_addr = inet_addr( host ); if( (int)addr.sin_addr.s_addr == -1 ) { hResponse.iError = errno; hResponse.pError = strerror( errno ); fprintf( stderr, "Unknown host %s\n", host ); if( path ) free( path ); if( pRequest ) free( pRequest ); return( hResponse ); } } else { memcpy( (char *)&addr.sin_addr.s_addr, nameinfo->h_addr, nameinfo->h_length ); } /* Create socket and connect */ if( (s = socket( PF_INET, SOCK_STREAM, 0 )) == -1 ) { hResponse.iError = errno; hResponse.pError = strerror( errno ); if( path ) free( path ); if( pRequest ) free( pRequest ); return( hResponse ); } if(in_Extra != NULL) in_Extra->Socket = s; addr.sin_family = AF_INET; addr.sin_port = htons( port ); if( connect( s, (struct sockaddr *)&addr, sizeof(addr) ) == -1 ) { hResponse.iError = errno; hResponse.pError = strerror( errno ); if( path ) free( path ); if( pRequest ) free( pRequest ); close( s ); return( hResponse ); } debug( stderr, "Connected to %s:%d\n", host, port ); // at this point we can construct our actual request. I'm trying to // incorporate more methods than the GET method supported by httpget switch( in_Method ) { case kHMethodPost: { debug( stderr, "top of post\n" ); /* The POST will come to us as two parts : * 1) The URL, in in_URL * 2) Some data (binary or ASCII), in in_Extra->PostData */ /* Check if we have some POST data. Note that in_Extra * is usually NULL for GET requests */ if((in_Extra == NULL) || (in_Extra->PostData == NULL)) { hResponse.iError = errno; hResponse.pError = "ERROR, invalid URL for POST request"; fprintf( stderr, "ERROR: invalid URL for POST request, no content found\n" ); if( path ) free( path ); if( pRequest ) free( pRequest ); close( s ); return( hResponse ); } sprintf( pRequest, "POST %s HTTP/1.0\r\nHost: %s\r\n", path, host ); /* "Content-Length" is mandatory for POST request, both for * security reason (you may DoS the server without) and because * we may send binary data. Jean II */ sprintf( szContent, "%s%d\r\n", "Content-Length: ", in_Extra->PostLen ); strcat( pRequest, szContent ); // the following Content-Type may need to be changed // depending on what type of data you are sending, // and/or if the data is encoded. ajd 8/28/2001 /* If the caller provides already a "Content-Type" header (below), * no need to do it ourselves - Jean II */ if( ! (in_Flags & HFLAG_POST_USER_TYPE) ) strcat( pRequest, "Content-Type: application/x-www-form-urlencoded\r\n"); /* Additional HTTP headers, most likely "Content-Type" */ if((in_Extra != NULL) && (in_Extra->Headers != NULL)) { strcat( pRequest, in_Extra->Headers ); strcat( pRequest, "\r\n" ); } strcat( pRequest, "User-Agent: hget/" LIBHTTP_VERSION "\r\n"); strcat( pRequest, "Pragma: no-cache\r\n" ); strcat( pRequest, "Accept: */*\r\n\r\n" ); break; } case kHMethodHead: { sprintf( pRequest, "HEAD %s HTTP/1.0\r\nHost: %s\r\n", path, host ); strcat( pRequest, "User-Agent: hget/" LIBHTTP_VERSION "\r\n"); if((in_Extra != NULL) && (in_Extra->Headers != NULL)) { strcat( pRequest, in_Extra->Headers ); strcat( pRequest, "\r\n" ); } strcat( pRequest, "Pragma: no-cache\r\n" ); strcat( pRequest, "Accept: */*\r\n\r\n" ); break; } case kHMethodGet: default: // currently GET is default! { // added in the Host: header entity // as that was preventing some servers // from responding properly. sprintf( pRequest, "GET %s HTTP/1.0\r\nHost: %s\r\n", path, host ); strcat( pRequest, "User-Agent: hget/" LIBHTTP_VERSION "\r\n"); if((in_Extra != NULL) && (in_Extra->Headers != NULL)) { strcat( pRequest, in_Extra->Headers ); strcat( pRequest, "\r\n" ); } strcat( pRequest, "Pragma: no-cache\r\n" ); strcat( pRequest, "Accept: */*\r\n\r\n" ); break; } } #ifdef DEBUG gettimeofday( &from_request, NULL ); #endif debug( stderr, "----- HTTP request follows -----\n" ); debug( stderr, "%s\n", pRequest ); debug( stderr, "----- HTTP request end -----\n" ); write( s, pRequest, strlen( pRequest) ); /* In the case of Post Request, we also need to send the payload * in the body of the request (following the header we have just * sent). Jean II */ if( in_Method == kHMethodPost ) write( s, in_Extra->PostData, in_Extra->PostLen ); /* Note : we don't display via debug the content of in_Extra->PostData, * because it may be binary and BIG. Jean II */ /* Cleanup. Those guys are no longer needed. Jean II */ if( path ) free( path ); if( pRequest ) free( pRequest ); /* --------------------------------------------------------- */ /* We sent everything, waiting for answer. Jean II */ FD_ZERO( &set ); FD_SET( s, &set ); if( select( FD_SETSIZE, &set, NULL, NULL, NULL ) == -1 ) { hResponse.iError = errno; hResponse.pError = strerror( errno ); close( s ); return( hResponse ); } #ifdef DEBUG gettimeofday( &from_reply, NULL ); #endif in_header = 1; total_bytes = 0UL; /* Allocate the working Rx buffer. We read data in this buffer * before doing the reassembly in pBase. Jean II */ pBuf = (char *)malloc( BUFLEN + 1 ); if( pBuf == NULL ) { hResponse.iError = errno; hResponse.pError = strerror( errno ); close( s ); return( hResponse ); } // first we'll allocate a 64k chunk of memory. we don't know the exact size of the // response. Most web pages fit in 64k of memory, and the is practical. for larger // transfer I typically like to allocate more up front. Alter to your preference. // I have tested this transfering a 32mb image using 64k allocations of memory and // 8k of read buffer. // ajd 8/27/2001 data_size = 0UL; pBase = (char *)malloc( XFERLEN ); if( pBase == NULL ) { hResponse.iError = errno; hResponse.pError = strerror( errno ); fprintf(stderr, "ERROR (malloc): recv (errno = %d = %s)\n", errno, strerror(errno)); fflush( stderr ); if( pBuf ) free( pBuf ); close( s ); return( hResponse ); } alloc_size = XFERLEN; pData = pBase; // assign the data ptr as base to start // for better or worse I've // decided to allocate 64k chunks // and use 8k for a working buffer. while( (bytes = read( s, pBuf, BUFLEN )) != 0 ) { total_bytes += bytes; debug( stderr, "data_size: %ld, alloc_size: %ld, total_bytes: %ld\n", data_size, alloc_size, total_bytes ); if( (data_size + bytes ) > alloc_size ) { pBase = realloc( pBase, (alloc_size + XFERLEN) ); if( pBase == NULL ) { // get outta dodge and free the // the allocated memory...there // could be a chance that we ran // out of resource, and we'll // free it. hResponse.iError = errno; hResponse.pError = strerror( errno ); fprintf(stderr, "ERROR (realloc): (errno = %d = %s)\n", errno, strerror(errno)); fflush( stderr ); if( pBase ) free( pBase ); if( pBuf ) free( pBuf ); close( s ); return( hResponse ); } pData = pBase + data_size; alloc_size += XFERLEN; debug( stderr, "." ); } memcpy( pData, pBuf, bytes ); // copy data pData += bytes; // increment pointer data_size += bytes; // increment size of data } #ifdef DEBUG gettimeofday( &end, NULL ); #endif close( s ); debug( stderr, "\nConnection closed.\n" ); #ifdef DEBUG if( end.tv_usec < from_reply.tv_usec ) { end.tv_sec -= 1; end.tv_usec += 1000000; } usecs = end.tv_usec - from_reply.tv_usec; secs = end.tv_sec - from_reply.tv_sec; debug( stderr, "Total of %ld bytes read in %ld.%ld seconds\n", total_bytes, secs, usecs ); if( secs != 0 ) { bytes_per_sec = (int)((total_bytes / (float)secs) + 0.5); debug( stderr, "%ld bytes per second\n", bytes_per_sec ); fflush( stderr ); } #endif h_end_ptr = find_header_end( pBase, total_bytes ); if( h_end_ptr != NULL ) { // we'll get response and response message pHCode = strchr( pBase, ' ' ); if( pHCode != NULL ) { pHCode++; strncpy( hResponse.szHCode, pHCode, 3 ); // now get message pHCode += 4; // increment past code // and search for new line pHMsgEnd = strchr( pHCode, '\n' ); if( pHMsgEnd != NULL ) // get the rest of line for the response message { strncpy( hResponse.szHMsg, pHCode, (pHMsgEnd - pHCode) <= (HMSGSIZE - 1) ? (pHMsgEnd - pHCode ) : (HMSGSIZE - 1) ); } } } else { header_size = total_bytes; h_end_ptr = pBase + total_bytes; } // now we'll store the size of the header, since we'll need to // subtract that from the total of bytes downloaded to get the // real size of the data. header_size = (unsigned long)(h_end_ptr - pBase); /* Found, print up to delimiter to stderr and rest to stdout */ debug( stderr, "----- HTTP reply header follows -----\n" ); debug2( pBase, h_end_ptr - pBase, 1, stderr ); debug( stderr, "----- HTTP reply header end -----\n" ); debug( stderr, "Header size: %d\n", header_size ); if( in_Method == kHMethodHead ) { if( pBuf ) free( pBuf ); pBase = realloc( pBase, header_size + 1 ); if( pBase == NULL ) return( hResponse ); pBase[header_size] = '\0'; hResponse.lSize = (long)header_size; hResponse.pData = pBase; return( hResponse ); } /* Does the client wants the header ? - Jean II */ if( in_Flags & HFLAG_RETURN_HEADER ) { /* Allocate it => client will cleanup */ hResponse.pHdr = malloc( header_size + 1 ); /* Don't make a big deal if it fails */ if( hResponse.pHdr != NULL ) { memcpy( hResponse.pHdr, pBase, header_size ); /* Be nice to client : NULL terminate it */ hResponse.pHdr[header_size] = '\0'; } } /* Delete HTTP headers */ memcpy(pBase, h_end_ptr, total_bytes - header_size); // realloc the data if we've gotten anything. chances are // we'll have more allocated than we've transfered. ajd 8/27/2001 if( (total_bytes - header_size) > 0 ) { pBase = realloc( pBase, (total_bytes - header_size) + 1 ); if( pBase == NULL ) { hResponse.iError = errno; hResponse.pError = strerror( errno ); fprintf(stderr, "ERROR (realloc): (errno = %d = %s)\n", errno, strerror(errno)); fflush( stderr ); if( pBase ) free( pBase ); if( pBuf ) free( pBuf ); return( hResponse ); } } // now, if we've gotten this far we must // have our data, so store the size and // the pointer to the data in our response // structure for return. if( in_Method != kHMethodHead ) // HEAD would be set already { pBase[total_bytes - header_size] = '\0'; hResponse.lSize = (long)(total_bytes - header_size); hResponse.pData = pBase; } if( pBuf ) free( pBuf ); return( hResponse ); }
int start_server(const char *url, const char *rtspport) { int mediafd = -1, listenfd, tempfd, maxfd; int videofd; struct addrinfo *info; struct sockaddr_storage remoteaddr; socklen_t addrlen = sizeof remoteaddr; fd_set readfds, masterfds; struct timeval *timeout, *timeind = NULL, timenow; int nready, i; int videosize, videoleft; int recvd, sent; char urlhost[URLSIZE], urlpath[URLSIZE], tempstr[URLSIZE]; unsigned char msgbuf[BUFSIZE], sendbuf[BUFSIZE]; char *temp; unsigned char *sps = NULL, *pps = NULL; size_t spslen, ppslen; RTSPMsg rtspmsg; Client streamclient; pthread_t threadid; ThreadInfo *tinfo = NULL; uint16_t rtpseqno_video = (rand() % 1000000); uint16_t rtpseqno_audio = (rand() % 1000000); TimeoutEvent *event; /* The current state of the protocol */ int mediastate = IDLE; int quit = 0; int media_downloaded = 0; timeout = (struct timeval *)malloc(sizeof(struct timeval)); init_client(&streamclient); /* Open the a file where the video is to be stored */ if ((videofd = open("videotemp.mp4", O_RDWR | O_CREAT | O_TRUNC, S_IRWXU)) < 0) { fatal_error("Error opening the temporary videofile"); } /* Create the RTSP listening socket */ resolve_host(NULL, rtspport, SOCK_STREAM, AI_PASSIVE, &info); listenfd = server_socket(info); maxfd = listenfd; FD_ZERO(&readfds); FD_ZERO(&masterfds); FD_SET(listenfd, &masterfds); while (!quit) { readfds = masterfds; if ((nready = Select(maxfd + 1, &readfds, timeind)) == -1) { printf("Select interrupted by a signal\n"); } /* Timeout handling, used for packet pacing and other timeouts */ else if (nready == 0) { timeind = NULL; lock_mutex(&queuelock); if ((event = pull_event(&queue)) != NULL) { switch (event->type) { case ENDOFSTREAM: printf("MEDIA FINISHED\n"); break; case FRAME: /* Video frame */ if (event->frame->frametype == VIDEO_FRAME) { rtpseqno_video += send_video_frame(sendbuf, event->frame, streamclient.videofds[0], rtpseqno_video); } /* Audio frame */ else { rtpseqno_audio += send_audio_frame(sendbuf, event->frame, streamclient.audiofds[0], rtpseqno_audio); } free(event->frame->data); free(event->frame); break; case CHECKMEDIASTATE: oma_debug_print("Checking media ready for streaming...\n"); if (mediastate != STREAM) { printf("Sending dummy RTP\n"); send_dummy_rtp(sendbuf, streamclient.videofds[0], &rtpseqno_video); push_timeout(&queue, 1000, CHECKMEDIASTATE); } break; default: oma_debug_print("ERRORENOUS EVENT TYPE!\n"); break; } /* If there are elements left in the queue, calculate next timeout */ if (queue.size > 0) { *timeout = calculate_delta(&event->time, &queue.first->time); timeind = timeout; oma_debug_print("Timeout: %ld secs, %ld usecs\n", timeout->tv_sec, timeout->tv_usec); } else { oma_debug_print("The first entry of the queue is NULL!\n"); } if (queue.size < QUEUESIZE / 2) { oma_debug_print("Signaling thread to start filling the queue"); pthread_cond_signal(&queuecond); } free(event); } unlock_mutex(&queuelock); continue; } /* End of timeout handling */ /* Start to loop through the file descriptors */ for (i = 0; i <= maxfd; i++) { if (FD_ISSET(i, &readfds)) { nready--; /* New connection from a client */ if (i == listenfd) { oma_debug_print("Recieved a new RTSP connection\n"); fflush(stdout); if ((tempfd = accept(i, (struct sockaddr *)&remoteaddr, &addrlen)) == -1) { if (errno != EWOULDBLOCK && errno != ECONNABORTED && errno != EPROTO && errno != EINTR) { fatal_error("accept"); } } /* If we are already serving a client, close the new connection. Otherwise, continue. */ if (streamclient.state != NOCLIENT) { printf("Another RTSP client tried to connect. Sorry, we can only serve one client at a time\n"); close (tempfd); } else { streamclient.rtspfd = tempfd; streamclient.state = CLICONNECTED; maxfd = max(2, streamclient.rtspfd, maxfd); FD_SET(streamclient.rtspfd, &masterfds); } } /* Data from the media source */ else if (i == mediafd) { switch (mediastate) { case GETSENT: /* Read ONLY the HTTP message from the socket and store the video size */ recvd = recv_all(i, msgbuf, BUFSIZE, MSG_PEEK); temp = strstr((char *)msgbuf, "\r\n\r\n"); recvd = recv_all(i, msgbuf, (int)(temp + 4 - (char *)msgbuf), 0); printf("Received HTTP response\n%s\n", msgbuf); temp = strstr((char *)msgbuf, "Content-Length:"); sscanf(temp, "Content-Length: %d", &videosize); videoleft = videosize; mediastate = RECVTCP; break; case RECVTCP: if ((recvd = recv_all(i, msgbuf, BUFSIZE, 0)) == 0) { FD_CLR(i, &masterfds); close(i); oma_debug_print("Socket closed\n"); } oma_debug_print("Received data from video source!\n"); writestr(videofd, msgbuf, recvd); videoleft -= recvd; if (videoleft <= 0) { printf("Video download complete.\n"); FD_CLR(mediafd, &masterfds); close(videofd); close(mediafd); media_downloaded = 1; printf("Media socket closed\n"); /* Create the context and the queue filler thread parameter struct */ tinfo = (ThreadInfo *)malloc(sizeof(ThreadInfo)); initialize_context(&tinfo->ctx, "videotemp.mp4", &tinfo->videoIdx, &tinfo->audioIdx, &tinfo->videoRate, &tinfo->audioRate, &sps, &spslen, &pps, &ppslen); /* Launch the queue filler thread */ CHECK((pthread_create(&threadid, NULL, fill_queue, tinfo)) == 0); pthread_detach(threadid); /* Send the sprop-parameters before any other frames */ send_video_frame(sendbuf, create_sprop_frame(sps, spslen, 0), streamclient.videofds[0], rtpseqno_video++); send_video_frame(sendbuf, create_sprop_frame(pps, ppslen, 0), streamclient.videofds[0], rtpseqno_video++); g_free(sps); g_free(pps); lock_mutex(&queuelock); push_timeout(&queue, 1000, CHECKMEDIASTATE); unlock_mutex(&queuelock); mediastate = STREAM; } break; case STREAM: /* close(videofd); close(mediafd); close(listenfd); quit = 1; */ break; default: break; } } /* Data from a client ( i == streamclient.rtspfd) */ else { oma_debug_print("Received data from rtspfd\n"); fflush(stdout); if ((recvd = recv_all(i, msgbuf, BUFSIZE, 0)) == 0) { FD_CLR(i, &masterfds); close(i); oma_debug_print("RTSP client closed the connection\n"); streamclient.state = NOCLIENT; } else { oma_debug_print("%s", msgbuf); parse_rtsp(&rtspmsg, msgbuf); } if (rtspmsg.type == TEARDOWN) { /* Kill thread and empty queue */ lock_mutex(&queuelock); pthread_cancel(threadid); empty_queue(&queue); sleep(1); /* Reply with 200 OK */ sent = rtsp_teardown(&rtspmsg, sendbuf); send_all(i, sendbuf, sent); FD_CLR(i, &masterfds); close(i); close(streamclient.videofds[0]); close(streamclient.videofds[1]); close(streamclient.audiofds[0]); close(streamclient.audiofds[1]); printf("Closing AVFormatContext\n"); close_context(tinfo->ctx); free(tinfo); rtpseqno_video = (rand() % 1000000) + 7; rtpseqno_audio = rtpseqno_video + 9; init_client(&streamclient); printf("Closing RTSP client sockets (RTP&RTCP)\n"); streamclient.state = NOCLIENT; unlock_mutex(&queuelock); pthread_cond_signal(&queuecond); } switch (streamclient.state) { case CLICONNECTED: if (rtspmsg.type == OPTIONS) { sent = rtsp_options(&rtspmsg, &streamclient, sendbuf); send_all(i, sendbuf, sent); } else if (rtspmsg.type == DESCRIBE) { if (media_downloaded == 0) { /* Start fetching the file from the server */ parse_url(url, urlhost, urlpath); resolve_host(urlhost, "80", SOCK_STREAM, 0, &info); mediafd = client_socket(info, 0); FD_SET(mediafd, &masterfds); maxfd = max(2, maxfd, mediafd); /* Send the GET message */ http_get(url, msgbuf); send_all(mediafd, msgbuf, strlen((char *)msgbuf)); mediastate = GETSENT; } else { mediastate = STREAM; } /* Send the SDP without sprop-parameter-sets, those are sent * later in-band */ streamclient.state = SDPSENT; sent = rtsp_describe(&streamclient, sendbuf); send_all(i, sendbuf, sent); } break; case SDPSENT: if (rtspmsg.type == SETUP) { streamclient.setupsreceived++; /* Open up the needed ports and bind them locally. The RTCP ports opened here * are not really used by this application. */ write_remote_ip(tempstr, streamclient.rtspfd); oma_debug_print("Remote IP: %s\n", tempstr); if (streamclient.setupsreceived < 2) { resolve_host(tempstr, rtspmsg.clirtpport, SOCK_DGRAM, 0, &info); streamclient.audiofds[0] = client_socket(info, streamclient.server_rtp_audio_port); resolve_host(tempstr, rtspmsg.clirtcpport, SOCK_DGRAM, 0, &info); streamclient.audiofds[1] = client_socket(info, streamclient.server_rtcp_audio_port); sent = rtsp_setup(&rtspmsg, &streamclient, sendbuf, streamclient.server_rtp_audio_port, streamclient.server_rtcp_audio_port); } else { resolve_host(tempstr, rtspmsg.clirtpport, SOCK_DGRAM, 0, &info); streamclient.videofds[0] = client_socket(info, streamclient.server_rtp_video_port); resolve_host(tempstr, rtspmsg.clirtcpport, SOCK_DGRAM, 0, &info); streamclient.audiofds[1] = client_socket(info, streamclient.server_rtcp_video_port); sent = rtsp_setup(&rtspmsg, &streamclient, sendbuf, streamclient.server_rtp_video_port, streamclient.server_rtcp_video_port); streamclient.state = SETUPCOMPLETE; } oma_debug_print("Sending setup response...\n"); send_all(i, sendbuf, sent); } break; case SETUPCOMPLETE: if (rtspmsg.type == PLAY) { /* Respond to the PLAY request, and start sending dummy RTP packets * to disable the client timeout */ sent = rtsp_play(&rtspmsg, sendbuf); send_all(i, sendbuf, sent); if (media_downloaded == 0) { lock_mutex(&queuelock); push_timeout(&queue, 100, CHECKMEDIASTATE); unlock_mutex(&queuelock); } /* Media has already been once downloaded, initialize context and thread */ else { tinfo = (ThreadInfo *)malloc(sizeof(ThreadInfo)); initialize_context(&tinfo->ctx, "videotemp.mp4", &tinfo->videoIdx, &tinfo->audioIdx, &tinfo->videoRate, &tinfo->audioRate, &sps, &spslen, &pps, &ppslen); /* Launch the queue filler thread */ CHECK((pthread_create(&threadid, NULL, fill_queue, tinfo)) == 0); pthread_detach(threadid); /* Send the sprop-parameters before any other frames */ send_video_frame(sendbuf, create_sprop_frame(sps, spslen, 0), streamclient.videofds[0], rtpseqno_video++); send_video_frame(sendbuf, create_sprop_frame(pps, ppslen, 0), streamclient.videofds[0], rtpseqno_video++); g_free(sps); g_free(pps); /* Dummy timeouts to start queue/timeout mechanism */ push_timeout(&queue, 100, CHECKMEDIASTATE); push_timeout(&queue, 2000, CHECKMEDIASTATE); } } break; default: break; } } } if (nready <= 0) break; } /* Set the timeout value again, since select will mess it up */ lock_mutex(&queuelock); if (queue.size > 0) { CHECK((gettimeofday(&timenow, NULL)) == 0); *timeout = calculate_delta(&timenow, &queue.first->time); /* oma_debug_print("Delta sec: %ld, Delta usec: %ld\n", timeout->tv_sec, timeout->tv_usec); */ if (timeout->tv_sec < 0) { timeout->tv_sec = 0; timeout->tv_usec = 0; } timeind = timeout; } else timeind = NULL; unlock_mutex(&queuelock); } return 1; }
static guint do_request(GWeb *web, const char *url, const char *type, GWebInputFunc input, int fd, gsize length, GWebResultFunc func, GWebRouteFunc route, gpointer user_data) { struct web_session *session; if (!web || !url) return 0; debug(web, "request %s", url); session = g_try_new0(struct web_session, 1); if (!session) return 0; if (parse_url(session, url, web->proxy) < 0) { free_session(session); return 0; } debug(web, "address %s", session->address); debug(web, "port %u", session->port); debug(web, "host %s", session->host); debug(web, "flags %lu", session->flags); debug(web, "request %s", session->request); if (type) { session->content_type = g_strdup(type); debug(web, "content-type %s", session->content_type); } session->web = web; session->result_func = func; session->route_func = route; session->input_func = input; session->fd = fd; session->length = length; session->offset = 0; session->user_data = user_data; session->receive_buffer = g_try_malloc(DEFAULT_BUFFER_SIZE); if (!session->receive_buffer) { free_session(session); return 0; } session->result.headers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); if (!session->result.headers) { free_session(session); return 0; } session->receive_space = DEFAULT_BUFFER_SIZE; session->send_buffer = g_string_sized_new(0); session->current_header = g_string_sized_new(0); session->header_done = false; session->body_done = false; if (!session->address && inet_aton(session->host, NULL) == 0) { session->resolv_action = g_resolv_lookup_hostname(web->resolv, session->host, resolv_result, session); if (session->resolv_action == 0) { free_session(session); return 0; } } else { struct addrinfo hints; char *port; int ret; if (!session->address) session->address = g_strdup(session->host); memset(&hints, 0, sizeof(struct addrinfo)); hints.ai_flags = AI_NUMERICHOST; hints.ai_family = session->web->family; if (session->addr) { freeaddrinfo(session->addr); session->addr = NULL; } port = g_strdup_printf("%u", session->port); ret = getaddrinfo(session->address, port, &hints, &session->addr); g_free(port); if (ret != 0 || !session->addr) { free_session(session); return 0; } if (create_transport(session) < 0) { free_session(session); return 0; } } web->session_list = g_list_append(web->session_list, session); return web->next_query_id++; }
static void download_one_url(const char *url) { bool use_proxy; /* Use proxies if env vars are set */ int redir_limit; len_and_sockaddr *lsa; FILE *sfp; /* socket to web/ftp server */ FILE *dfp; /* socket to ftp server (data) */ char *proxy = NULL; char *fname_out_alloc; struct host_info server; struct host_info target; server.allocated = NULL; target.allocated = NULL; server.user = NULL; target.user = NULL; parse_url(url, &target); /* Use the proxy if necessary */ use_proxy = (strcmp(G.proxy_flag, "off") != 0); if (use_proxy) { proxy = getenv(target.is_ftp ? "ftp_proxy" : "http_proxy"); use_proxy = (proxy && proxy[0]); if (use_proxy) parse_url(proxy, &server); } if (!use_proxy) { server.port = target.port; if (ENABLE_FEATURE_IPV6) { //free(server.allocated); - can't be non-NULL server.host = server.allocated = xstrdup(target.host); } else { server.host = target.host; } } if (ENABLE_FEATURE_IPV6) strip_ipv6_scope_id(target.host); /* If there was no -O FILE, guess output filename */ fname_out_alloc = NULL; if (!(option_mask32 & WGET_OPT_OUTNAME)) { G.fname_out = bb_get_last_path_component_nostrip(target.path); /* handle "wget http://kernel.org//" */ if (G.fname_out[0] == '/' || !G.fname_out[0]) G.fname_out = (char*)"index.html"; /* -P DIR is considered only if there was no -O FILE */ else { if (G.dir_prefix) G.fname_out = fname_out_alloc = concat_path_file(G.dir_prefix, G.fname_out); else { /* redirects may free target.path later, need to make a copy */ G.fname_out = fname_out_alloc = xstrdup(G.fname_out); } } } #if ENABLE_FEATURE_WGET_STATUSBAR G.curfile = bb_get_last_path_component_nostrip(G.fname_out); #endif /* Determine where to start transfer */ G.beg_range = 0; if (option_mask32 & WGET_OPT_CONTINUE) { G.output_fd = open(G.fname_out, O_WRONLY); if (G.output_fd >= 0) { G.beg_range = xlseek(G.output_fd, 0, SEEK_END); } /* File doesn't exist. We do not create file here yet. * We are not sure it exists on remote side */ } redir_limit = 5; resolve_lsa: lsa = xhost2sockaddr(server.host, server.port); if (!(option_mask32 & WGET_OPT_QUIET)) { char *s = xmalloc_sockaddr2dotted(&lsa->u.sa); fprintf(stderr, "Connecting to %s (%s)\n", server.host, s); free(s); } establish_session: /*G.content_len = 0; - redundant, got_clen = 0 is enough */ G.got_clen = 0; G.chunked = 0; if (use_proxy || !target.is_ftp) { /* * HTTP session */ char *str; int status; /* Open socket to http server */ sfp = open_socket(lsa); /* Send HTTP request */ if (use_proxy) { fprintf(sfp, "GET %stp://%s/%s HTTP/1.1\r\n", target.is_ftp ? "f" : "ht", target.host, target.path); } else { if (option_mask32 & WGET_OPT_POST_DATA) fprintf(sfp, "POST /%s HTTP/1.1\r\n", target.path); else fprintf(sfp, "GET /%s HTTP/1.1\r\n", target.path); } fprintf(sfp, "Host: %s\r\nUser-Agent: %s\r\n", target.host, G.user_agent); /* Ask server to close the connection as soon as we are done * (IOW: we do not intend to send more requests) */ fprintf(sfp, "Connection: close\r\n"); #if ENABLE_FEATURE_WGET_AUTHENTICATION if (target.user) { //TODO: URL-decode "user:password" string before base64-encoding: //wget http://test:my%[email protected] should send // Authorization: Basic dGVzdDpteSBwYXNz //which decodes to "test:my pass", instead of what we send now: // Authorization: Basic dGVzdDpteSUyMHBhc3M= //Can reuse decodeString() from httpd.c fprintf(sfp, "Proxy-Authorization: Basic %s\r\n"+6, base64enc(target.user)); } if (use_proxy && server.user) { fprintf(sfp, "Proxy-Authorization: Basic %s\r\n", base64enc(server.user)); } #endif if (G.beg_range) fprintf(sfp, "Range: bytes=%"OFF_FMT"u-\r\n", G.beg_range); #if ENABLE_FEATURE_WGET_LONG_OPTIONS if (G.extra_headers) fputs(G.extra_headers, sfp); if (option_mask32 & WGET_OPT_POST_DATA) { fprintf(sfp, "Content-Type: application/x-www-form-urlencoded\r\n" "Content-Length: %u\r\n" "\r\n" "%s", (int) strlen(G.post_data), G.post_data ); } else #endif { fprintf(sfp, "\r\n"); } fflush(sfp); /* * Retrieve HTTP response line and check for "200" status code. */ read_response: fgets_and_trim(sfp); str = G.wget_buf; str = skip_non_whitespace(str); str = skip_whitespace(str); // FIXME: no error check // xatou wouldn't work: "200 OK" status = atoi(str); switch (status) { case 0: case 100: while (gethdr(sfp) != NULL) /* eat all remaining headers */; goto read_response; case 200: /* Response 204 doesn't say "null file", it says "metadata has changed but data didn't": "10.2.5 204 No Content The server has fulfilled the request but does not need to return an entity-body, and might want to return updated metainformation. The response MAY include new or updated metainformation in the form of entity-headers, which if present SHOULD be associated with the requested variant. If the client is a user agent, it SHOULD NOT change its document view from that which caused the request to be sent. This response is primarily intended to allow input for actions to take place without causing a change to the user agent's active document view, although any new or updated metainformation SHOULD be applied to the document currently in the user agent's active view. The 204 response MUST NOT include a message-body, and thus is always terminated by the first empty line after the header fields." However, in real world it was observed that some web servers (e.g. Boa/0.94.14rc21) simply use code 204 when file size is zero. */ case 204: break; case 300: /* redirection */ case 301: case 302: case 303: break; case 206: if (G.beg_range) break; /* fall through */ default: bb_error_msg_and_die("server returned error: %s", sanitize_string(G.wget_buf)); } /* * Retrieve HTTP headers. */ while ((str = gethdr(sfp)) != NULL) { static const char keywords[] ALIGN1 = "content-length\0""transfer-encoding\0""location\0"; enum { KEY_content_length = 1, KEY_transfer_encoding, KEY_location }; smalluint key; /* gethdr converted "FOO:" string to lowercase */ /* strip trailing whitespace */ char *s = strchrnul(str, '\0') - 1; while (s >= str && (*s == ' ' || *s == '\t')) { *s = '\0'; s--; } key = index_in_strings(keywords, G.wget_buf) + 1; if (key == KEY_content_length) { G.content_len = BB_STRTOOFF(str, NULL, 10); if (G.content_len < 0 || errno) { bb_error_msg_and_die("content-length %s is garbage", sanitize_string(str)); } G.got_clen = 1; continue; } if (key == KEY_transfer_encoding) { if (strcmp(str_tolower(str), "chunked") != 0) bb_error_msg_and_die("transfer encoding '%s' is not supported", sanitize_string(str)); G.chunked = 1; } if (key == KEY_location && status >= 300) { if (--redir_limit == 0) bb_error_msg_and_die("too many redirections"); fclose(sfp); if (str[0] == '/') { free(target.allocated); target.path = target.allocated = xstrdup(str+1); /* lsa stays the same: it's on the same server */ } else { parse_url(str, &target); if (!use_proxy) { free(server.allocated); server.allocated = NULL; server.host = target.host; /* strip_ipv6_scope_id(target.host); - no! */ /* we assume remote never gives us IPv6 addr with scope id */ server.port = target.port; free(lsa); goto resolve_lsa; } /* else: lsa stays the same: we use proxy */ } goto establish_session; } } // if (status >= 300) // bb_error_msg_and_die("bad redirection (no Location: header from server)"); /* For HTTP, data is pumped over the same connection */ dfp = sfp; } else {
/** * Simple command-line HTTP client. */ int main( int argc, char *argv[ ] ) { int client_connection; char *host, *path; char *proxy_host, *proxy_user, *proxy_password; int proxy_port; struct hostent *host_name; struct sockaddr_in host_address; int port = HTTPS_PORT; int ind; int master_secret_length; unsigned char *master_secret; int session_id_length; unsigned char *session_id; #ifdef WIN32 WSADATA wsaData; #endif TLSParameters tls_context; if ( argc < 2 ) { fprintf( stderr, "Usage: %s: [-p http://[username:password@]proxy-host:proxy-port] <URL>\n", argv[ 0 ] ); return 1; } proxy_host = proxy_user = proxy_password = host = path = session_id = master_secret = NULL; session_id_length = master_secret_length = 0; for ( ind = 1; ind < ( argc - 1 ); ind++ ) { if ( !strcmp( "-p", argv[ ind ] ) ) { if ( !parse_proxy_param( argv[ ++ind ], &proxy_host, &proxy_port, &proxy_user, &proxy_password ) ) { fprintf( stderr, "Error - malformed proxy parameter '%s'.\n", argv[ 2 ] ); return 2; } } else if ( !strcmp( "-s", argv[ ind ] ) ) { session_id_length = hex_decode( argv[ ++ind ], &session_id ); } else if ( !strcmp( "-m", argv[ ind ] ) ) { master_secret_length = hex_decode( argv[ ++ind ], &master_secret ); } } if ( ( ( master_secret_length > 0 ) && ( session_id_length == 0 ) ) || ( ( master_secret_length == 0 ) && ( session_id_length > 0 ) ) ) { fprintf( stderr, "session id and master secret must both be provided.\n" ); return 3; } if ( parse_url( argv[ ind ], &host, &path ) == -1 ) { fprintf( stderr, "Error - malformed URL '%s'.\n", argv[ 1 ] ); return 1; } printf( "Connecting to host '%s'\n", host ); // Step 1: open a socket connection on http port with the destination host. #ifdef WIN32 if ( WSAStartup( MAKEWORD( 2, 2 ), &wsaData ) != NO_ERROR ) { fprintf( stderr, "Error, unable to initialize winsock.\n" ); return 2; } #endif client_connection = socket( PF_INET, SOCK_STREAM, 0 ); if ( !client_connection ) { perror( "Unable to create local socket" ); return 2; } if ( proxy_host ) { printf( "Connecting to host '%s'\n", proxy_host ); host_name = gethostbyname( proxy_host ); } else { host_name = gethostbyname( host ); } if ( !host_name ) { perror( "Error in name resolution" ); return 3; } host_address.sin_family = AF_INET; host_address.sin_port = htons( proxy_host ? proxy_port : HTTPS_PORT ); memcpy( &host_address.sin_addr, host_name->h_addr_list[ 0 ], sizeof( struct in_addr ) ); if ( connect( client_connection, ( struct sockaddr * ) &host_address, sizeof( host_address ) ) == -1 ) { perror( "Unable to connect to host" ); return 4; } printf( "Connection complete; negotiating TLS parameters\n" ); if ( session_id != NULL ) { if ( tls_resume( client_connection, session_id_length, session_id, master_secret, &tls_context ) ) { fprintf( stderr, "Error: unable to negotiate SSL connection.\n" ); if ( close( client_connection ) == -1 ) { perror( "Error closing client connection" ); return 2; } return 3; } } else { if ( tls_connect( client_connection, &tls_context, 0 ) ) { fprintf( stderr, "Error: unable to negotiate TLS connection.\n" ); return 3; } } printf( "Retrieving document: '%s'\n", path ); http_get( client_connection, path, host, &tls_context ); display_result( client_connection, &tls_context ); tls_shutdown( client_connection, &tls_context ); printf( "Session ID was: " ); show_hex( tls_context.session_id, tls_context.session_id_length ); printf( "Master secret was: " ); show_hex( tls_context.master_secret, MASTER_SECRET_LENGTH ); printf( "Shutting down.\n" ); #ifdef WIN32 if ( closesocket( client_connection ) == -1 ) #else if ( close( client_connection ) == -1 ) #endif { perror( "Error closing client connection" ); return 5; } if ( session_id != NULL ) { free( session_id ); } if ( master_secret != NULL ) { free( master_secret ); } #ifdef WIN32 WSACleanup(); #endif return 0; }
static void parse_line (Package *pkg, const char *untrimmed, const char *path, gboolean ignore_requires, gboolean ignore_private_libs, gboolean ignore_requires_private) { char *str; char *p; char *tag; debug_spew (" line>%s\n", untrimmed); str = trim_string (untrimmed); if (*str == '\0') /* empty line */ { g_free(str); return; } p = str; /* Get first word */ while ((*p >= 'A' && *p <= 'Z') || (*p >= 'a' && *p <= 'z') || (*p >= '0' && *p <= '9') || *p == '_' || *p == '.') p++; tag = g_strndup (str, p - str); while (*p && isspace ((guchar)*p)) ++p; if (*p == ':') { /* keyword */ ++p; while (*p && isspace ((guchar)*p)) ++p; if (strcmp (tag, "Name") == 0) parse_name (pkg, p, path); else if (strcmp (tag, "Description") == 0) parse_description (pkg, p, path); else if (strcmp (tag, "Version") == 0) parse_version (pkg, p, path); else if (strcmp (tag, "Requires.private") == 0) { if (!ignore_requires_private) parse_requires_private (pkg, p, path); } else if (strcmp (tag, "Requires") == 0) { if (ignore_requires == FALSE) parse_requires (pkg, p, path); else goto cleanup; } else if ((strcmp (tag, "Libs.private") == 0) && ignore_private_libs == FALSE) parse_libs_private (pkg, p, path); else if (strcmp (tag, "Libs") == 0) parse_libs (pkg, p, path); else if (strcmp (tag, "Cflags") == 0 || strcmp (tag, "CFlags") == 0) parse_cflags (pkg, p, path); else if (strcmp (tag, "Conflicts") == 0) parse_conflicts (pkg, p, path); else if (strcmp (tag, "URL") == 0) parse_url (pkg, p, path); else { /* we don't error out on unknown keywords because they may * represent additions to the .pc file format from future * versions of pkg-config. We do make a note of them in the * debug spew though, in order to help catch mistakes in .pc * files. */ debug_spew ("Unknown keyword '%s' in '%s'\n", tag, path); } } else if (*p == '=') { /* variable */ char *varname; char *varval; ++p; while (*p && isspace ((guchar)*p)) ++p; if (pkg->vars == NULL) pkg->vars = g_hash_table_new (g_str_hash, g_str_equal); #ifdef G_OS_WIN32 if (!dont_define_prefix && strcmp (tag, prefix_variable) == 0) { /* This is the prefix variable. Try to guesstimate a value for it * for this package from the location of the .pc file. */ gchar *prefix = pkg->pcfiledir; const int prefix_len = strlen (prefix); const char *const lib_pkgconfig = "\\lib\\pkgconfig"; const char *const share_pkgconfig = "\\share\\pkgconfig"; const int lib_pkgconfig_len = strlen (lib_pkgconfig); const int share_pkgconfig_len = strlen (share_pkgconfig); if ((strlen (prefix) > lib_pkgconfig_len && pathnamecmp (prefix + prefix_len - lib_pkgconfig_len, lib_pkgconfig) == 0) || (strlen (prefix) > share_pkgconfig_len && pathnamecmp (prefix + prefix_len - share_pkgconfig_len, share_pkgconfig) == 0)) { /* It ends in lib\pkgconfig or share\pkgconfig. Good. */ gchar *q; orig_prefix = g_strdup (p); prefix = g_strdup (prefix); if (strlen (prefix) > lib_pkgconfig_len && pathnamecmp (prefix + prefix_len - lib_pkgconfig_len, lib_pkgconfig) == 0) prefix[prefix_len - lib_pkgconfig_len] = '\0'; else prefix[prefix_len - share_pkgconfig_len] = '\0'; /* Turn backslashes into slashes or * poptParseArgvString() will eat them when ${prefix} * has been expanded in parse_libs(). */ q = prefix; while (*q) { if (*q == '\\') *q = '/'; q++; } varname = g_strdup (tag); debug_spew (" Variable declaration, '%s' overridden with '%s'\n", tag, prefix); g_hash_table_insert (pkg->vars, varname, prefix); goto cleanup; } } else if (!dont_define_prefix && orig_prefix != NULL && strncmp (p, orig_prefix, strlen (orig_prefix)) == 0 && G_IS_DIR_SEPARATOR (p[strlen (orig_prefix)])) { char *oldstr = str; p = str = g_strconcat (g_hash_table_lookup (pkg->vars, prefix_variable), p + strlen (orig_prefix), NULL); g_free (oldstr); } #endif if (g_hash_table_lookup (pkg->vars, tag)) { verbose_error ("Duplicate definition of variable '%s' in '%s'\n", tag, path); exit (1); } varname = g_strdup (tag); varval = trim_and_sub (pkg, p, path); debug_spew (" Variable declaration, '%s' has value '%s'\n", varname, varval); g_hash_table_insert (pkg->vars, varname, varval); } cleanup: g_free (str); g_free (tag); }
int validate_stream(media_entry * p, SD_descr ** sd_descr) { RTP_static_payload pt_info; char object[255], server[255]; unsigned short port; int res; if (!(p->flags & ME_FILENAME)) { return ERR_PARSE; } if (!(p->description.flags & MED_PAYLOAD_TYPE)) { return ERR_PARSE; } if (!(p->description.flags & MED_PRIORITY)) { return ERR_PARSE; } /* *- validate multicast *- validate twin * */ if (parse_url ((*sd_descr)->twin, server, sizeof(server), &port, object, sizeof(object))) (*sd_descr)->flags &= ~SD_FL_TWIN; if (!is_valid_multicast_address((*sd_descr)->multicast)) strcpy((*sd_descr)->multicast, DEFAULT_MULTICAST_ADDRESS); if (p->description.payload_type >= 96) { // Basic information needed for a dynamic payload type (96-127) if (!(p->description.flags & MED_ENCODING_NAME)) { return ERR_PARSE; } if (!(p->description.flags & MED_CLOCK_RATE)) { return ERR_PARSE; } } else { // Set payload type for well-kwnown encodings and some default configurations if i know them // see include/fenice/rtpptdefs.h pt_info = RTP_payload[p->description.payload_type]; if (!(p->description.flags & MED_ENCODING_NAME) || (strcmp(p->description.encoding_name, "RTP_SHM"))) strcpy(p->description.encoding_name, pt_info.EncName); p->description.clock_rate = pt_info.ClockRate; p->description.audio_channels = pt_info.Channels; p->description.bit_per_sample = pt_info.BitPerSample; p->description.coding_type = pt_info.Type; p->description.pkt_len = pt_info.PktLen; p->description.flags |= MED_ENCODING_NAME; p->description.flags |= MED_CLOCK_RATE; p->description.flags |= MED_AUDIO_CHANNELS; p->description.flags |= MED_BIT_PER_SAMPLE; p->description.flags |= MED_CODING_TYPE; // p->description.flags|=MED_PKT_LEN; } res = register_media(p); if (res == ERR_NOERROR) return p->media_handler->load_media(p); else return res; }
/* * handle_request - handle one HTTP request from client and * make request for actual server. It will wait for response * and forward response back to client. */ void handle_request(int clientfd) { char buf[MAXLINE], method[MAXLINE], url[MAXLINE]; char hostname[MAXLINE], uri[MAXLINE], version[MAXLINE]; rio_t rio; char port[] = "80"; /* http request use port 80 */ /* Read request line and headers */ Rio_readinitb(&rio, clientfd); Rio_readlineb(&rio, buf, MAXLINE); sscanf(buf, "%s %s %s", method, url, version); if (strcasecmp(method, "GET")) { clienterror(clientfd, method, "501", "Not Implemented", "Proxy does not implement this method"); return; } parse_url(url, hostname, uri); /* connect to host server by hostname */ int serverfd; if ((serverfd = open_clientfd(hostname, port)) < 0) { pthread_mutex_lock(&print_lock); printf("Open_clientfd error\n"); pthread_mutex_unlock(&print_lock); return; } /* construct a new request line */ char requestLine[MAXLINE]; strcpy(requestLine, method); strcat(requestLine, uri); strcat(requestLine, "HTTP/1.0"); rio_readinitb(&rio, serverfd); rio_writen(serverfd, buf, strlen(buf)); /* send request line to server */ /* read and send request header to server */ char requesthrds[MAXLINE]; cat_requesthdrs(requesthrds, hostname); rio_writen(serverfd, requesthrds, strlen(requesthrds)); //rio_readlineb(&rio, buf, MAXLINE); //rio_writen(serverfd, buf, strlen(buf)); //while(strcmp(buf, "\r\n")) //{ // rio_readlineb(&rio, buf, MAXLINE); // rio_writen(serverfd, buf, strlen(buf)); //} char emptyline[] = "\r\n"; rio_writen(serverfd, emptyline, strlen(emptyline)); /* get response from server and send it back to client */ rio_writen(clientfd, emptyline, strlen(emptyline)); read_requesthdrs(&rio); size_t n; while ((n = rio_readlineb(&rio, buf, MAXLINE)) != 0) rio_writen(clientfd, buf, strlen(buf)); /* close connection to server */ int rc; if ((rc = close(serverfd)) < 0) { pthread_mutex_lock(&print_lock); printf("Close error\n"); pthread_mutex_unlock(&print_lock); } pthread_mutex_lock(&print_lock); printf("Connection to server closed.\n"); pthread_mutex_unlock(&print_lock); }
int init (int argc, char *argv[]) { char *p; int rc = 0, oldmode; url_t u; int x0=-1, y0=-1, r=-1, c=-1; struct hostent *remote; char buffer[MAX_PATH]; if (action == ACTION_TESTONLY) exit (0); if (action == ACTION_BADAGS) { usage (); exit (1); } if (options.keep_winsize) { r = cfg_get_integer (CONFIG_NFTP, fl_opt.platform_nick, "rows"); c = cfg_get_integer (CONFIG_NFTP, fl_opt.platform_nick, "cols"); if (r == 0 && c == 0) r = -1, c = -1; } if (options.keep_winpos) { x0 = cfg_get_integer (CONFIG_NFTP, fl_opt.platform_nick, "x0"); y0 = cfg_get_integer (CONFIG_NFTP, fl_opt.platform_nick, "y0"); if (x0 == 0 || y0 == 0) x0 = -1, y0 = -1; } p = cfg_get_string (CONFIG_NFTP, fl_opt.platform_nick, "font"); if (p[0] == '\0') p = NULL; fly_init (x0, y0, r, c, p); if (options.show_hw_cursor) video_cursor_state (1); fly_mouse (options.mouse); wintitle = get_window_name (); if (fl_opt.platform == PLATFORM_OS2_VIO) { strcpy (buffer, paths.system_libpath); str_cats (buffer, "nftp.ico"); if (access (buffer, R_OK) == 0) set_icon (buffer); } if (main_menu != NULL) { menu_activate (main_menu); adjust_menu_status (); } display.dir_mode = options.defaultdirmode; display.view_mode = VIEW_CONTROL; display.rshift = 0; display.lshift = 0; display.tabsize = 8; if (options.slowlink) set_view_mode (VIEW_REMOTE); else set_view_mode (VIEW_CONTROL); site.maxndir = 1024; site.dir = malloc (sizeof(directory)*site.maxndir); // ignore "broken PIPE" signals signal (SIGPIPE, SIG_IGN); set_window_name ("NFTP%s(C) Copyright Sergey Ayukov", NFTP_VERSION); local.dir.files = NULL; local.sortmode = abs (options.default_localsort); if (options.default_localsort >= 0) local.sortdirection = 1; else local.sortdirection = -1; build_local_filelist (NULL); site.batch_mode = FALSE; site.chunks = NULL; PutLineIntoResp2 ("NFTP Version%s(%s, %s) -- %s", NFTP_VERSION, __DATE__, __TIME__, fl_opt.platform_name); PutLineIntoResp1 ("Copyright (C) 1994-2003 Sergey Ayukov <*****@*****.**>"); PutLineIntoResp1 ("Portions Copyright (C) Eric Young <*****@*****.**>"); //PutLineIntoResp1 ("Portions Copyright (C) Martin Nicolay <*****@*****.**>"); status.usage_interval = 0; if (!fl_opt.has_osmenu) PutLineIntoResp1 (M("Press F9 or Ctrl-F for menu")); update (1); if (options.firewall_type != 0) { if (options.fire_server[0] == '\0') { fly_ask_ok (ASK_WARN, M("Firewall proxy host isn't specified in NFTP.INI")); options.firewall_type = 0; } else { if (strspn (options.fire_server, " .0123456789") == strlen (options.fire_server)) { firewall.fwip = inet_addr (options.fire_server); } else { PutLineIntoResp2 (M("Looking up '%s'"), options.fire_server); remote = gethostbyname (options.fire_server); if (remote == NULL) { PutLineIntoResp2 (M("Cannot find '%s'"), options.fire_server); options.firewall_type = 0; } else { firewall.fwip = *((unsigned long *)(remote->h_addr)); PutLineIntoResp2 (M("Found '%s'"), remote->h_name); } } } } // read password cache psw_read (); // analyze arguments switch (action) { case 0: if (options.download_path != NULL) { set_local_path (options.download_path); } else { p = cfg_get_string (CONFIG_NFTP, "", "local-directory"); if (p[0] != '\0') set_local_path (p); } build_local_filelist (NULL); switch (options.start_prompt) { case 1: return FMSG_BASE_MENU + KEY_GEN_LOGIN; case 2: return FMSG_BASE_MENU + KEY_GEN_BOOKMARKS; case 3: return FMSG_BASE_MENU + KEY_GEN_HISTORY; case 5: return FMSG_BASE_MENU + KEY_MENU; } return 0; case ACTION_DOWNLOAD: case ACTION_UPLOAD: oldmode = site.batch_mode; site.batch_mode = TRUE; if (action == ACTION_DOWNLOAD) rc = do_get (optarg1); if (action == ACTION_UPLOAD) rc = do_put (optarg1); //set_view_mode (VIEW_CONTROL); //update (1); if (rc && !cmdline.batchmode) fly_ask_ok (0, M("Transfer of '%s' has failed"), optarg1); if ((disc_after && rc == 0) || cmdline.batchmode) { Logoff (); terminate (); exit (0); } site.batch_mode = oldmode; return 0; case ACTION_CMDLIST: rc = runscript (optarg1); return 0; case ACTION_NICK_BOOK: case ACTION_NICK_HIST: if (action == ACTION_NICK_BOOK && bookmark_nickname (optarg1, &u) == 0) return 0; if (action == ACTION_NICK_HIST && history_nickname (optarg1, &u) == 0) return 0; rc = Login (&u); if (rc) return 0; if (options.login_bell) Bell (3); return 0; case ACTION_OPEN_BOOKMARKS: return FMSG_BASE_MENU + KEY_GEN_BOOKMARKS; case ACTION_OPEN_HISTORY: return FMSG_BASE_MENU + KEY_GEN_HISTORY; case ACTION_LOGIN: // if download_path was specified in nftp.ini, set it now if (options.download_path != NULL) set_local_path (options.download_path); build_local_filelist (NULL); parse_url (optarg1, &u); rc = Login (&u); // attempt to download file if chdir failed /*if (site.set_up && strcmp (site.u.pathname, RCURDIR.name) != 0) { rc = do_get (optarg1); } if (rc) return 0; */ if (options.login_bell) Bell (3); return 0; case ACTION_TESTONLY: terminate (); exit (0); } fly_error ("internal error in init()"); return 0; }
static HRESULT connect_channel( struct channel *channel, WS_MESSAGE *msg ) { static const WCHAR agentW[] = {'M','S','-','W','e','b','S','e','r','v','i','c','e','s','/','1','.','0',0}; static const WCHAR postW[] = {'P','O','S','T',0}; HINTERNET ses = NULL, con = NULL, req = NULL; WCHAR *path; URL_COMPONENTS uc; DWORD flags = 0; HRESULT hr; if ((hr = parse_url( channel->addr.url.chars, channel->addr.url.length, &uc )) != S_OK) return hr; if (!uc.dwExtraInfoLength) path = uc.lpszUrlPath; else if (!(path = heap_alloc( (uc.dwUrlPathLength + uc.dwExtraInfoLength + 1) * sizeof(WCHAR) ))) { hr = E_OUTOFMEMORY; goto done; } else { strcpyW( path, uc.lpszUrlPath ); strcatW( path, uc.lpszExtraInfo ); } switch (uc.nScheme) { case INTERNET_SCHEME_HTTP: break; case INTERNET_SCHEME_HTTPS: flags |= WINHTTP_FLAG_SECURE; break; default: FIXME( "scheme %u not supported\n", uc.nScheme ); hr = E_NOTIMPL; goto done; } if (!(ses = WinHttpOpen( agentW, 0, NULL, NULL, 0 ))) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto done; } if (!(con = WinHttpConnect( ses, uc.lpszHostName, uc.nPort, 0 ))) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto done; } if (!(req = WinHttpOpenRequest( con, postW, path, NULL, NULL, NULL, flags ))) { hr = HRESULT_FROM_WIN32( GetLastError() ); goto done; } if ((hr = message_insert_http_headers( msg, req )) != S_OK) goto done; channel->http_session = ses; channel->http_connect = con; channel->http_request = req; done: if (hr != S_OK) { WinHttpCloseHandle( req ); WinHttpCloseHandle( con ); WinHttpCloseHandle( ses ); } heap_free( uc.lpszHostName ); heap_free( uc.lpszUrlPath ); heap_free( uc.lpszExtraInfo ); if (path != uc.lpszUrlPath) heap_free( path ); return hr; }
int main(int argc, char *argv[]) { char buf[BUFLEN]; char request[MAXPATHLEN + 20]; char scheme[50], host[MAXPATHLEN], path[MAXPATHLEN]; char *url; char *proxy; int port; int reload = 0; struct hostent *nameinfo; int s; struct sockaddr_in addr; struct timeval from_request, from_reply, end; long total_bytes, bytes; fd_set set; int in_header; char *h_end_ptr; long secs, usecs, bytes_per_sec; if (argc < 2) { fprintf(stderr, "Wrong number of arguments.\n"); fprintf(stderr, "Usage: httpget -r http://host.name/path/to/document.html\n"); exit(1); } if (!strcmp(argv[1], "-r")) { reload = 1; } url = argv[argc - 1]; if ((proxy = getenv("http_proxy")) == NULL) { parse_url(url, scheme, host, &port, path); fprintf(stderr, "URL scheme = %s\n", scheme); fprintf(stderr, "URL host = %s\n", host); fprintf(stderr, "URL port = %d\n", port); fprintf(stderr, "URL path = %s\n", path); if (strcasecmp(scheme, "http") != 0) { fprintf(stderr, "httpget cannot operate on %s URLs without a proxy\n", scheme); exit(1); } } else { parse_url(proxy, scheme, host, &port, path); fprintf(stderr, "Using proxy server at %s:%d\n", host, port); } /* Find out the IP address */ if ((nameinfo = gethostbyname(host)) == NULL) { addr.sin_addr.s_addr = inet_addr(host); if ((int)addr.sin_addr.s_addr == -1) { fprintf(stderr, "Unknown host %s\n", host); exit(1); } } else { memcpy((char *)&addr.sin_addr.s_addr, nameinfo->h_addr, nameinfo->h_length); } /* Create socket and connect */ if ((s = socket(PF_INET, SOCK_STREAM, 0)) == -1) { perror("httpget: socket()"); exit(1); } addr.sin_family = AF_INET; addr.sin_port = htons(port); if (connect(s, (struct sockaddr *)&addr, sizeof(addr)) == -1) { perror("httpget: connect()"); exit(1); } fprintf(stderr, "Connected to %s:%d\n", host, port); if (proxy) { fprintf(stderr, "Sending URL %s to proxy...\n", url); sprintf(request, "GET %s HTTP/1.0\r\n", url); } else { fprintf(stderr, "Sending request...\n"); sprintf(request, "GET %s HTTP/1.0\r\n", path); } if (reload) { strcat(request, "Pragma: no-cache\r\n"); } strcat(request, "Accept: */*\r\n\r\n"); gettimeofday(&from_request, NULL); write(s, request, strlen(request)); FD_ZERO(&set); FD_SET(s, &set); if (select(FD_SETSIZE, &set, NULL, NULL, NULL) == -1) { perror("httpget: select()"); exit(1); } gettimeofday(&from_reply, NULL); fprintf(stderr, "----- HTTP reply header follows -----\n"); in_header = 1; total_bytes = 0; while ((bytes = read(s, buf, BUFLEN)) != 0) { total_bytes += bytes; if (in_header) { /* Search for the reply header delimiter (blank line) */ h_end_ptr = find_header_end(buf, total_bytes); if (h_end_ptr != NULL) { /* Found, print up to delimiter to stderr and rest to stdout */ fwrite(buf, h_end_ptr - buf, 1, stderr); fprintf(stderr, "----- HTTP reply header end -----\n"); fwrite(h_end_ptr, bytes - (h_end_ptr - buf), 1, stdout); in_header = 0; } else { /* Not found, print all in buf to stderr and read for more headers */ fwrite(buf, bytes, 1, stderr); } fflush(stderr); } else { fwrite(buf, bytes, 1, stdout); } } gettimeofday(&end, NULL); close(s); fprintf(stderr, "Connection closed.\n"); if (end.tv_usec < from_reply.tv_usec) { end.tv_sec -= 1; end.tv_usec += 1000000; } usecs = end.tv_usec - from_reply.tv_usec; secs = end.tv_sec - from_reply.tv_sec; fprintf(stderr, "Total of %ld bytes read in %ld.%ld seconds\n", total_bytes, secs, usecs); if (secs != 0) { bytes_per_sec = (int)((total_bytes / (float)secs) + 0.5); fprintf(stderr, "%ld bytes per second\n", bytes_per_sec); } exit(0); }
static PT_THREAD(handle_request(connection_state_t* conn_state)) { static int error; const char* content_len; PSOCK_BEGIN(&(conn_state->sin)); content_len = NULL; error = HTTP_NO_ERROR; /*always reinit static variables due to protothreads*/ PRINTF("Request--->\n"); //read method PSOCK_READTO(&(conn_state->sin), ' '); if (!is_method_handled(conn_state, conn_state->inputbuf)) { /*method not handled*/ http_set_status(&conn_state->response, SERVICE_UNAVAILABLE_503); conn_state->state = STATE_OUTPUT; } else { /*read until the end of url*/ PSOCK_READTO(&(conn_state->sin), ' '); /*-1 is needed since it also includes space char*/ if (conn_state->inputbuf[PSOCK_DATALEN(&(conn_state->sin)) - 1] != ' ' ) { error = HTTP_URL_TOO_LONG; } conn_state->inputbuf[PSOCK_DATALEN(&(conn_state->sin)) - 1] = 0; PRINTF("Read URL:%s\n", conn_state->inputbuf); if (error == HTTP_NO_ERROR) { error = parse_url(conn_state, conn_state->inputbuf); } if (error != HTTP_NO_ERROR) { if (error == HTTP_URL_TOO_LONG) { http_set_status(&conn_state->response, REQUEST_URI_TOO_LONG_414); } else { http_set_status(&conn_state->response, BAD_REQUEST_400); } conn_state->state = STATE_OUTPUT; } else { /*read until the end of HTTP version - not used yet*/ PSOCK_READTO(&(conn_state->sin), LINE_FEED_CHAR); PRINTF("After URL:%s\n", conn_state->inputbuf); /*FIXME : PSOCK_READTO takes just a single delimiter so I read till the end of line but now it may not fit in the buffer. If PSOCK_READTO would take two delimiters, we would have read until : and <CR> so it would not be blocked.*/ /*Read the headers and store the necessary ones*/ do { /*read the next line*/ PSOCK_READTO(&(conn_state->sin), LINE_FEED_CHAR); conn_state->inputbuf[ PSOCK_DATALEN(&(conn_state->sin)) - 1] = 0; /*if headers finished then stop the infinite loop*/ if (conn_state->inputbuf[0] == CARRIAGE_RETURN_CHAR || conn_state->inputbuf[0] == 0) { PRINTF("Finished Headers!\n\n"); break; } parse_header(conn_state, conn_state->inputbuf); } while(1); content_len = get_header(conn_state->request.headers, HTTP_HEADER_NAME_CONTENT_LENGTH); if (content_len) { conn_state->request.payload_len = atoi(content_len); PRINTF("Post Data Size string: %s int: %d\n", content_len, conn_state->request.payload_len); } if (conn_state->request.payload_len) { static uint16_t read_bytes = 0; /*init the static variable again*/ read_bytes = 0; conn_state->request.payload = allocate_buffer(conn_state->request.payload_len + 1); if (conn_state->request.payload) { do { PSOCK_READBUF(&(conn_state->sin)); /*null terminate the buffer in case it is a string.*/ conn_state->inputbuf[PSOCK_DATALEN(&(conn_state->sin))] = 0; memcpy(conn_state->request.payload + read_bytes, conn_state->inputbuf, PSOCK_DATALEN(&(conn_state->sin))); read_bytes += PSOCK_DATALEN(&(conn_state->sin)); } while (read_bytes < conn_state->request.payload_len); conn_state->request.payload[read_bytes++] = 0; PRINTF("PostData => %s \n", conn_state->request.payload); } else { error = HTTP_MEMORY_ALLOC_ERR; } } if (error == HTTP_NO_ERROR) { if (service_cbk) { service_cbk(&conn_state->request, &conn_state->response); } } else { PRINTF("Error:%d\n",error); http_set_status(&conn_state->response, INTERNAL_SERVER_ERROR_500); } conn_state->state = STATE_OUTPUT; } } PSOCK_END(&(conn_state->sin)); }
static int request_lookup(struct connman_service *service, const char *url) { DBusMessage *msg; DBusPendingCall *call; dbus_bool_t result; char *host; struct proxy_data *data; DBG(""); if (!daemon_running) return -EINVAL; msg = dbus_message_new_method_call(PACRUNNER_SERVICE, PACRUNNER_CLIENT_PATH, PACRUNNER_CLIENT_INTERFACE, "FindProxyForURL"); if (!msg) return -1; host = parse_url(url); if (!host) { dbus_message_unref(msg); return -EINVAL; } data = g_try_new0(struct proxy_data, 1); if (!data) { dbus_message_unref(msg); g_free(host); return -ENOMEM; } data->url = g_strdup(url); data->service = connman_service_ref(service); dbus_message_set_auto_start(msg, FALSE); dbus_message_append_args(msg, DBUS_TYPE_STRING, &url, DBUS_TYPE_STRING, &host, DBUS_TYPE_INVALID); result = dbus_connection_send_with_reply(connection, msg, &call, DBUS_TIMEOUT); dbus_message_unref(msg); if (!result || !call) { g_free(host); g_free(data->url); g_free(data); return -EINVAL; } dbus_pending_call_set_notify(call, request_lookup_reply, data, NULL); dbus_pending_call_unref(call); g_free(host); return 0; }
/* * Once the user has authorized the request key, we can exchange it for an access key * This function implements the logic required to do so. * Once you get back the new/exchanged accessToken and accessSecret you can use it for issuing requests * to the sevice from now on */ int oauth_exchange_reqtoken(const char *fullUrl, const char *consumerKey, const char *consumerSecret, const char *oauthToken, const char *oauthTokenSecret, struct string *accessToken, struct string *accessSeret) { struct url_props url; struct string headers; struct http_response resp; const char *p, *e; if (parse_url(fullUrl, &url)) return -1; string_reset(accessToken); string_reset(accessSeret); string_init(&headers); oauth_signandappend_oauth_header("GET", &url, consumerKey, consumerSecret, oauthToken, oauthTokenSecret, time(NULL), NULL, 0, NULL, NULL, NULL, &headers); http_response_init(&resp); if (http_request(&url, "GET", &headers, NULL, &resp)) goto onFailure; p = resp.body + resp.headersSize; e = p + resp.contentLen; printf("3 Parsing [%.*s]\n", e - p, p); while (p != e) { const char *name = p; while (p != e) { if (*p == '=') break; ++p; } if (p != e) { const size_t nameLen = p - name; const char *value = ++p; size_t valueLen; printf("[%.*s]\n", (signed)nameLen, name); for (; p != e && *p != '&'; ++p) continue; valueLen = p - value; if (nameLen == 11 && memcmp(name, "oauth_token", 11) == 0) string_append(accessToken, value, valueLen); else if (nameLen == 18 && memcmp(name, "oauth_token_secret", 18) == 0) string_append(accessSeret, value, valueLen); printf("value =[%.*s]\n", (signed)valueLen, value); if (p != e) ++p; else break; } else break; } if (string_len(accessToken) && string_len(accessSeret)) { string_dealloc(&headers); http_response_dealloc(&resp); return 0; } onFailure: string_dealloc(&headers); http_response_dealloc(&resp); return -1; }
// returun http response code int get_url_doc(const char* url, char* response_status, char* redirect_url) { //printf("\n"); //printf("*Target url : %s\n", url); // break down the url to know the host and path char url_host[256] = {0,}; char url_path[256] = {0,}; int port = 80; parse_url(url, url_host, &port, url_path); // we need to find the ip for the host struct hostent *hostent; if((hostent = gethostbyname(url_host)) == NULL) { sprintf(response_status, "gethostbyname() error"); return -1; } // create socket int rsockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(rsockfd < 0) { sprintf(response_status, "socket() error"); return -1; } struct sockaddr_in host_addr; bzero((char*)&host_addr, sizeof(host_addr)); host_addr.sin_port = htons(port); host_addr.sin_family = AF_INET; bcopy((char*)hostent->h_addr, (char*)&host_addr.sin_addr.s_addr, hostent->h_length); // try connecting to the remote host if(connect(rsockfd, (struct sockaddr*)&host_addr, sizeof(struct sockaddr)) < 0) { sprintf(response_status, "connect() error"); close(rsockfd); return -1; } //printf("*Connected to IP: %s\n", inet_ntoa(host_addr.sin_addr)); char buffer[8192] = {0,}; // 8K sprintf(buffer,"GET %s HTTP/1.1\r\nHost: %s\r\nConnection: close\r\n\r\n", url_path, url_host); // send the request to remote host int n = send(rsockfd, buffer, strlen(buffer), 0); if(n < 0) { sprintf(response_status, "send() error"); close(rsockfd); return -1; } int response_code = 0; FILE* fp = NULL; int count_recv = 0; int content_len = 0; bool is_chunked_encoding = false; int remaind = 0; do { // recieve from remote host bzero((char*)buffer, sizeof(buffer)); n = recv(rsockfd, buffer, sizeof(buffer), 0); //printf("********* nrecv : %d\n", n); // if we have read anything - otherwise END-OF-FILE if(n > 0) { char* body = buffer; // if this is the first time we are here // meaning: we are reading the http response header if(count_recv++ == 0) { // read the first line to discover the response code float ver; sscanf(buffer, "HTTP/%f %d", &ver, &response_code); //printf("*Response Code: %d\n", response_code); // save first one line const char* p = strstr(buffer, "\r\n"); strncpy(response_status, buffer, p-buffer); if(response_code / 100 == 3) // 3XX { close(rsockfd); // read Location p = strstr(buffer, "Location: "); if(p != NULL) { sscanf(p, "Location: %s", redirect_url); //printf("*Location: %s\n", redirect_url); } return response_code; } if(response_code / 100 != 2) // 2XX { close(rsockfd); return response_code; } // read Content-Length p = strstr(buffer, "Content-Length:"); if(p!= NULL) { sscanf(p, "Content-Length: %d", &content_len); //printf("*Content-Length: %d\n", content_len); } // read Connection char connection[10] = {0,}; p = strstr(buffer, "Connection: "); if(p != NULL) { sscanf(p, "Connection: %s", connection); //printf("*Connection: %s\n", connection); } // read Content-Type char content_type[300] = {0,}; char content_type_ext[300] = {0,}; p = strstr(buffer, "Content-Type: "); if(p != NULL) { sscanf(p, "Content-Type: %s", content_type); //printf("*Content-Type: [%s]\n", content_type); char* pp = strstr(content_type, "/"); pp = pp == NULL ? content_type : pp + 1; strcpy(content_type_ext, pp); int size = strlen(content_type_ext); if(content_type_ext[size-1] == ';') content_type_ext[size-1] = 0; //printf("*Content-Type ext: [%s]\n", content_type_ext); } p = strstr(buffer, "Transfer-Encoding: chunked"); if(p != NULL) { is_chunked_encoding = true; //printf("chunked encoding !!\n"); } // open file for writing char fname[256] = {0,}; sprintf(fname, "./temp/%s.%s", url_host, content_type_ext); fp = fopen(fname, "w"); body = strstr(buffer, "\r\n\r\n") + 4; } //printf("%s", buffer); //printf("%s", body); if(content_len == 0) { if(is_chunked_encoding) // chunked encoding 처리 { int chunk_size = 0; const char* pchunk = body; // 직전에 다 읽지 못한 나머지 읽어 처리 if(remaind > 0) { //printf("remaind : %d\n", remaind); fwrite(pchunk, 1, remaind, fp); pchunk += remaind; remaind = 0; int cur_pos = pchunk - buffer; if(cur_pos >= n) continue; pchunk = strstr(pchunk, "\n") + 1; } // Loop 돌며 chunk 단위로 처리 while(true) { sscanf(pchunk, "%X", &chunk_size); //printf("chunk size : %d ( %x )\n", chunk_size, chunk_size); if(chunk_size == 0) break; pchunk = strstr(pchunk, "\n") + 1; int cur_pos = pchunk - buffer; //printf("cur pos : %d\n", cur_pos); //printf("cur pos + chunk_size : %d\n", cur_pos + chunk_size); if(cur_pos + chunk_size > n) { remaind = chunk_size; chunk_size = n - cur_pos; remaind -= chunk_size; //printf("llll - chunk size : %d ( %x )\n", chunk_size, chunk_size); fwrite(pchunk, 1, chunk_size, fp); break; } else { remaind = 0; fwrite(pchunk, 1, chunk_size, fp); pchunk += chunk_size; pchunk = strstr(pchunk, "\n") + 1; cur_pos = pchunk - buffer; //printf("cur pos : %d\n", cur_pos); if(cur_pos >= n) break; } } } else { fprintf(fp, "%s", body); } } else // Content-Length 가 헤더에 있을 경우 { int header_size = body - buffer; int body_size = sizeof(buffer) - header_size; if(content_len < body_size) body_size = content_len; int nwrite = fwrite(body, 1, body_size, fp); //printf("%d - content_len : %d nwrite : %d\n", count_recv, content_len, nwrite); content_len -= nwrite; } } } while(n > 0); if(fp != NULL) fclose(fp); close(rsockfd); return response_code; }
/* * Function: _wilddog_url_parseUrl * Description: parse url using wilddog format. * Input: url: Input url. * Output: N/A * Return: Pointer to the url structure. */ Wilddog_Url_T * WD_SYSTEM _wilddog_url_parseUrl(Wilddog_Str_T * url) { struct parsed_url * p_paresd_url = NULL; Wilddog_Url_T * p_wd_url = NULL; int len = 2; wilddog_assert(url, NULL); p_paresd_url = parse_url((char*)url); if(NULL == p_paresd_url) return NULL; p_wd_url = (Wilddog_Url_T *)wmalloc(sizeof(Wilddog_Url_T)); if(NULL == p_wd_url) { wilddog_debug_level(WD_DEBUG_ERROR, "cannot malloc p_wd_url!\n"); parsed_url_free(p_paresd_url); return NULL; } if(NULL != p_paresd_url->host) { p_wd_url->p_url_host = (Wilddog_Str_T *)wmalloc( \ strlen(p_paresd_url->host) + 1); if(NULL == p_wd_url->p_url_host) { wilddog_debug_level(WD_DEBUG_ERROR, "cannot malloc p_url_host!\n"); _wilddog_url_freeParsedUrl(p_wd_url); parsed_url_free(p_paresd_url); return NULL; } strncpy((char*)p_wd_url->p_url_host, (char*)p_paresd_url->host, \ strlen((const char*)p_paresd_url->host)); } else return NULL; if(NULL == p_paresd_url->path) { p_wd_url->p_url_path = (Wilddog_Str_T *)wmalloc(len); if(NULL == p_wd_url->p_url_path) { _wilddog_url_freeParsedUrl(p_wd_url); parsed_url_free(p_paresd_url); return NULL; } p_wd_url->p_url_path[0] = '/'; } else { len += strlen((const char*)p_paresd_url->path); if(WILDDOG_ERR_NOERR != \ _wilddogurl_checkPath((Wilddog_Str_T*)p_paresd_url->path) ) { #ifdef WILDDOG_ADD_ONLINESTAT //added by jimmy if(0 != strncmp((const char*)p_paresd_url->path, WILDDOG_ONLINE_PATH,strlen(WILDDOG_ONLINE_PATH))) #endif { _wilddog_url_freeParsedUrl(p_wd_url); parsed_url_free(p_paresd_url); return NULL; } } p_wd_url->p_url_path = (Wilddog_Str_T *)wmalloc(len + 1); if(NULL == p_wd_url->p_url_path) { _wilddog_url_freeParsedUrl(p_wd_url); parsed_url_free(p_paresd_url); return NULL; } snprintf((char*)p_wd_url->p_url_path, len, "/%s", \ p_paresd_url->path); len = strlen((const char*)p_wd_url->p_url_path); if(len > 1 && p_wd_url->p_url_path[len - 1] == '/') { p_wd_url->p_url_path[len - 1] = 0; } } if(NULL != p_paresd_url->query) { p_wd_url->p_url_query = (Wilddog_Str_T *)wmalloc( \ strlen((const char*)p_paresd_url->query) + 1); if(NULL == p_wd_url->p_url_query) { _wilddog_url_freeParsedUrl(p_wd_url); parsed_url_free(p_paresd_url); return NULL; } strncpy((char*)p_wd_url->p_url_query, (char*)p_paresd_url->query, \ strlen((const char*)p_paresd_url->query)); } parsed_url_free(p_paresd_url); return p_wd_url; }
void lazy_parse() const {if (!m_parse) parse_url();}
/*---------------------------------------------------------------------------*/ static void event(struct tcp_socket *tcps, void *ptr, tcp_socket_event_t e) { struct http_socket *s = ptr; char host[MAX_HOSTLEN]; char path[MAX_PATHLEN]; uint16_t port; char str[42]; int len; if(e == TCP_SOCKET_CONNECTED) { printf("Connected\n"); if(parse_url(s->url, host, &port, path)) { tcp_socket_send_str(tcps, s->postdata != NULL ? "POST " : "GET "); if(s->proxy_port != 0) { /* If we are configured to route through a proxy, we should provide the full URL as the path. */ tcp_socket_send_str(tcps, s->url); } else { tcp_socket_send_str(tcps, path); } tcp_socket_send_str(tcps, " HTTP/1.1\r\n"); tcp_socket_send_str(tcps, "Connection: close\r\n"); tcp_socket_send_str(tcps, "Host: "); /* If we have IPv6 host, add the '[' and the ']' characters to the host. As in rfc2732. */ if(memchr(host, ':', MAX_HOSTLEN)) { tcp_socket_send_str(tcps, "["); } tcp_socket_send_str(tcps, host); if(memchr(host, ':', MAX_HOSTLEN)) { tcp_socket_send_str(tcps, "]"); } tcp_socket_send_str(tcps, "\r\n"); if(s->postdata != NULL) { if(s->content_type) { tcp_socket_send_str(tcps, "Content-Type: "); tcp_socket_send_str(tcps, s->content_type); tcp_socket_send_str(tcps, "\r\n"); } tcp_socket_send_str(tcps, "Content-Length: "); sprintf(str, "%u", s->postdatalen); tcp_socket_send_str(tcps, str); tcp_socket_send_str(tcps, "\r\n"); } else if(s->length || s->pos > 0) { tcp_socket_send_str(tcps, "Range: bytes="); if(s->length) { if(s->pos >= 0) { sprintf(str, "%llu-%llu", s->pos, s->pos + s->length - 1); } else { sprintf(str, "-%llu", s->length); } } else { sprintf(str, "%llu-", s->pos); } tcp_socket_send_str(tcps, str); tcp_socket_send_str(tcps, "\r\n"); } tcp_socket_send_str(tcps, "\r\n"); if(s->postdata != NULL && s->postdatalen) { len = tcp_socket_send(tcps, s->postdata, s->postdatalen); s->postdata += len; s->postdatalen -= len; } } parse_header_init(s); } else if(e == TCP_SOCKET_CLOSED) { call_callback(s, HTTP_SOCKET_CLOSED, NULL, 0); removesocket(s); printf("Closed\n"); } else if(e == TCP_SOCKET_TIMEDOUT) { call_callback(s, HTTP_SOCKET_TIMEDOUT, NULL, 0); removesocket(s); printf("Timedout\n"); } else if(e == TCP_SOCKET_ABORTED) { call_callback(s, HTTP_SOCKET_ABORTED, NULL, 0); removesocket(s); printf("Aborted\n"); } else if(e == TCP_SOCKET_DATA_SENT) { if(s->postdata != NULL && s->postdatalen) { len = tcp_socket_send(tcps, s->postdata, s->postdatalen); s->postdata += len; s->postdatalen -= len; } else { start_timeout_timer(s); } } }
/* * main function to parse the http request header. */ int parse_request(struct http_header *header, char *request, size_t len) { char ch, *p = request; int tmp; while (p < request + len) // for(p = request; p < request + len; p++) { ch = *p; switch (GET_HEADER_STATE(header)) { // some error happened, // and then ignore all data left in the buffer. case s_dead: return -1; // finshed parsing http request header, // but there are still some data in the buffer. case s_done: return p - request; // start to parse METHOD case s_request_start: case s_method_start: { // skip space at the beginning if (CR == ch || LF == ch || SP == ch) { p++; break; } // when match the first non-space character // parse the http method tmp = parse_method(header, p); if (tmp == -1) { // failed SET_HEADER_STATE(header, s_dead); SET_HEADER_ERROR(header, e_invalid_method); return -1; } else if (tmp == E_INTERRUPT) { SET_HEADER_ERROR(header, e_again); return -1; } else { // success SET_HEADER_STATE(header, s_method_end); p += tmp; p++; break; } } // after found out the http method // there is an SP between METHOD and URL case s_method_end: { if (SP != ch) { // failed SET_HEADER_STATE(header, s_dead); SET_HEADER_ERROR(header, e_invalid_method); return -1; } else { // success SET_HEADER_STATE(header, s_url_start); p++; break; } } // start to parse URL case s_url_start: case s_path_start: case s_query_start: { // TODO // handle the CONNECT and OPTION method tmp = parse_url(header, p, len - (p - request)); if (tmp == -1) { // failed SET_HEADER_STATE(header, s_dead); SET_HEADER_ERROR(header, e_invalid_url); return -1; } else if (tmp == E_INTERRUPT) { SET_HEADER_ERROR(header, e_again); return -1; } else { SET_HEADER_STATE(header, s_version_start); p += tmp; p++; break; } } // http version, only support HTTP/1.0 and HTTP/1.1 case s_version_start: { int tmp = parse_version(header, p); if (tmp == -1) { SET_HEADER_STATE(header, s_dead); SET_HEADER_ERROR(header, e_invalid_version); return -1; } else if (tmp == E_INTERRUPT) { SET_HEADER_ERROR(header, e_again); return -1; } else { SET_HEADER_STATE(header, s_line_cr); p += HTTP_VERSION_LENGTH; break; } } // CR character in the end of line case s_line_cr: { if (CR == ch) { SET_HEADER_STATE(header, s_line_lf); p++; break; } else { SET_HEADER_STATE(header, s_dead); SET_HEADER_ERROR(header, e_eol); return -1; } } // LF character in the end of line case s_line_lf: { if (LF == ch) { SET_HEADER_STATE(header, s_done); break; } else { SET_HEADER_STATE(header, s_dead); SET_HEADER_ERROR(header, e_eol); return -1; } } // header field start case s_field_start: { SET_HEADER_STATE(header, s_done); break; } default: SET_HEADER_STATE(header, s_dead); } } // three results // dead, done, again switch (GET_HEADER_STATE(header)) { // error case s_dead: return s_dead; // finished case s_done: return s_done; // again default: SET_HEADER_ERROR(header, e_again); return s_dead; } }
/* **************************************************************** * DESCRIBE METHOD HANDLING **************************************************************** */ int RTSP_describe(RTSP_buffer * rtsp) { int valid_url, res; char object[255], server[255], trash[255]; char *p; unsigned short port; char url[255]; media_entry media, req; description_format descr_format = df_SDP_format; // shawill put to some default char descr[MAX_DESCR_LENGTH]; /* Extract la URL */ if (!sscanf(rtsp->in_buffer, " %*s %254s ", url)) { send_reply(400, 0, rtsp); /* bad request */ return ERR_NOERROR; } /* Validate the URL */ switch (parse_url(url, server, sizeof(server), &port, object, sizeof(object))) { case 1: // bad request send_reply(400, 0, rtsp); return ERR_NOERROR; break; case -1: // internal server error send_reply(500, 0, rtsp); return ERR_NOERROR; break; default: break; } if (strcmp(server, prefs_get_hostname()) != 0) { /* Currently this feature is disabled. */ /* wrong server name */ // send_reply(404, 0 , rtsp); /* Not Found */ // return ERR_NOERROR; } if (strstr(object, "../")) { /* disallow relative paths outside of current directory. */ send_reply(403, 0, rtsp); /* Forbidden */ return ERR_NOERROR; } if (strstr(object, "./")) { /* Disallow ./ */ send_reply(403, 0, rtsp); /* Forbidden */ return ERR_NOERROR; } p = strrchr(object, '.'); valid_url = 0; if (p == NULL) { send_reply(415, 0, rtsp); /* Unsupported media type */ return ERR_NOERROR; } else { valid_url = is_supported_url(p); } if (!valid_url) { send_reply(415, 0, rtsp); /* Unsupported media type */ return ERR_NOERROR; } // Disallow Header REQUIRE if (strstr(rtsp->in_buffer, HDR_REQUIRE)) { send_reply(551, 0, rtsp); /* Option not supported */ return ERR_NOERROR; } /* Get the description format. SDP is recomended */ if (strstr(rtsp->in_buffer, HDR_ACCEPT) != NULL) { if (strstr(rtsp->in_buffer, "application/sdp") != NULL) { descr_format = df_SDP_format; } else { // Add here new description formats send_reply(551, 0, rtsp); /* Option not supported */ return ERR_NOERROR; } } // Get the CSeq if ((p = strstr(rtsp->in_buffer, HDR_CSEQ)) == NULL) { send_reply(400, 0, rtsp); /* Bad Request */ return ERR_NOERROR; } else { if (sscanf(p, "%254s %d", trash, &(rtsp->rtsp_cseq)) != 2) { send_reply(400, 0, rtsp); /* Bad Request */ return ERR_NOERROR; } } memset(&media, 0, sizeof(media)); memset(&req, 0, sizeof(req)); req.flags = ME_DESCR_FORMAT; req.descr_format = descr_format; res = get_media_descr(object, &req, &media, descr); if (res == ERR_NOT_FOUND) { send_reply(404, 0, rtsp); // Not found return ERR_NOERROR; } if (res == ERR_PARSE || res == ERR_GENERIC || res == ERR_ALLOC) { send_reply(500, 0, rtsp); // Internal server error return ERR_NOERROR; } if(max_connection()==ERR_GENERIC){ /*redirect*/ return send_redirect_3xx(rtsp, object); } fnc_log(FNC_LOG_INFO,"DESCRIBE %s RTSP/1.0 ",url); send_describe_reply(rtsp, object, descr_format, descr); // See User-Agent if ((p=strstr(rtsp->in_buffer, HDR_USER_AGENT))!=NULL) { char cut[strlen(p)]; strcpy(cut,p); p=strstr(cut, "\n"); cut[strlen(cut)-strlen(p)-1]='\0'; fnc_log(FNC_LOG_CLIENT,"%s\n",cut); } else fnc_log(FNC_LOG_CLIENT,"- \n"); return ERR_NOERROR; }