📄 http_client.c
字号:
} } current->next= (socket_buffer *) malloc(sizeof(socket_buffer)); if (!current->next) { free_socket_buffers(&head); return UPNP_E_OUTOF_MEMORY; } current=current->next; current->next=NULL; current->size=0; nextToRead=SOCKET_BUFFER_SIZE; if (contentLength==-1) { if (chunk_size<SOCKET_BUFFER_SIZE) nextToRead=chunk_size; } else if (contentLength>0) { if (contentLength<SOCKET_BUFFER_SIZE) nextToRead=contentLength; } if ((HTTP_READ_BYTES!=-1) && ( (total_size+(nextToRead))>HTTP_READ_BYTES)) { done=1; break; } if ( (current->size=read_timeout(fd,current->buff,nextToRead,&Timeout))>0) { if (contentLength>0) { contentLength-=current->size; if (contentLength==0) { done=1; } } if (contentLength==-1) { chunk_size-=current->size; } total_size+=current->size; } else { if (current->size<0) { DBGONLY(UpnpPrintf(UPNP_CRITICAL,API,__FILE__,__LINE__,"socket read error, probably timed out")); current->size=0; } done=1; } } } if (total_size<0) { (*out)=NULL; free_socket_buffers(&head); return total_size; } (*out)=(char * ) malloc(total_size+1); concat_socket_buffers(&head,(*out)); (*out)[total_size]=0; free_socket_buffers(&head); return HTTP_SUCCESS;}//*************************************************************************//* Name: write_bytes//*//* Description: writes bytes to a socket with a timeout //* writes until all bytes are written//* //* In: int fd (socket)//* char *buf (buffer to be sent)//* size_t n (number of bytes to be sent)//* int timeout (timeout for operation)//*//* Out: # of bytes sent. //* //* Return Codes: >=0 success//* Error Codes: -1 (error writing socket, including//* timeout)//*************************************************************************size_t write_bytes(int fd, char * bytes, size_t n, int timeout){ int bytes_written=0; int bytes_left=n; char *ptr=bytes; int Timeout=timeout; while (bytes_left>0) { if ( (bytes_written=write_timeout(fd,ptr,bytes_left,&Timeout))<=0) return -1;//error bytes_left-=bytes_written; ptr+=bytes_written; } return bytes_written;}//*************************************************************************//* Name: transferHTTP//*//* Description: sends an http request, and returns the output in a //* null terminated string (allocated by function, freed by//* caller). automatically generates host line. if//* no path is given default path is '/'. HTTP version 1.1//* is used for everything except "GET"//* //* In: char * request (NULL terminated string, e.g. "GET")//* char * toSend (bytes to be sent AFTER the HOST header)//* int toSendSize (number of bytes in toSend)//* char ** out (output)//* URL (NULL terminated url)//*//* Out: HTTP_SUCCESS (on success) , (*out) null terminated string//* //* Return Codes: HTTP_SUCCESS//* Error Codes: UPNP_E_OUTOF_MEMORY//* UPNP_E_READ_SOCKET//* UPNP_E_WRITE_SOCKET//* UPNP_E_OUTOF_SOCKET//* UPNP_E_SOCKET_CONNECT//*//* Example: transferHTTP("GET","\r\n",2,&temp,//* "http://localhost:80/foo?silly#56");//* ------------------------------------------------------------//* A TCP conneciton is opened to localhost:80.//* The following is sent: //* "GET /foo?silly HTTP/1.1\r\nHOST: localhost:80\r\n\r\n"//*************************************************************************int transferHTTP( char * request, char * toSend, int toSendSize, char **out, char * Url){ uri_type parsed_url; int return_code=HTTP_SUCCESS; if ( (return_code=parse_uri(Url,strlen(Url),&parsed_url))==HTTP_SUCCESS ) { return transferHTTPparsedURL(request,toSend,toSendSize,out,&parsed_url); } else return return_code;}//*************************************************************************//* Name: transferHTTPRaw//*//* Description: sends an http request, and returns the output in a //* null terminated string (allocated by function, freed by//* caller). DOESN'T generate any headers//* //* In: //* char * toSend (bytes to be sent)//* int toSendSize (number of bytes in toSend)//* char ** out (output)//* URL (NULL terminated url)//*//* Out: HTTP_SUCCESS (on success) , (*out) null terminated string//* //* Return Codes: HTTP_SUCCESS//* Error Codes: UPNP_E_OUTOF_MEMORY//* UPNP_E_READ_SOCKET//* UPNP_E_WRITE_SOCKET//* UPNP_E_OUTOF_SOCKET//* UPNP_E_SOCKET_CONNECT//*//* Example: transferHTTP(//* "GET /foo?silly HTTP/1.1\r\nHOST: localhost:80\r\nfoo\r\n\r\n",//* strlen("GET /foo?silly HTTP/1.1\r\nHOST: localhost:80\r\nfoo\r\n\r\n")//* ,&temp,//* "http://localhost:80");//* ------------------------------------------------------------//* A TCP conneciton is opened to localhost:80.//* The following is sent: //* "GET /foo?silly HTTP/1.1\r\nHOST: localhost:80\r\nfoo\r\n\r\n"//*************************************************************************int transferHTTPRaw( char * toSend, int toSendSize, char **out, char * Url){ uri_type parsed_url; int return_code=HTTP_SUCCESS; int client_socket=0; if ( (return_code=parse_uri(Url,strlen(Url),&parsed_url))==HTTP_SUCCESS ) { //set up tcp connection if (token_string_casecmp(&parsed_url.scheme,"http")) { return UPNP_E_INVALID_URL; } if (parsed_url.hostport.text.size==0) { return UPNP_E_INVALID_URL; } if ( (client_socket=socket(AF_INET,SOCK_STREAM,0))==-1) { DBGONLY(UpnpPrintf(UPNP_CRITICAL,API,__FILE__,__LINE__,"OUT OF SOCKET")); return UPNP_E_OUTOF_SOCKET; } if (connect(client_socket,(struct sockaddr*) & parsed_url.hostport.IPv4address,sizeof(struct sockaddr))==-1) { close(client_socket); DBGONLY(UpnpPrintf(UPNP_CRITICAL,API,__FILE__,__LINE__,"CONNECT ERROR")); return UPNP_E_SOCKET_CONNECT; } //changed to transmit null character if ( write_bytes(client_socket,toSend, toSendSize,RESPONSE_TIMEOUT)==-1) { close(client_socket); DBGONLY(UpnpPrintf(UPNP_CRITICAL,API,__FILE__,__LINE__,"WRITE ERROR")); return UPNP_E_SOCKET_WRITE; } return_code=read_http_response(client_socket,out,RESPONSE_TIMEOUT); close(client_socket); return return_code; } else return return_code; }//*************************************************************************//* Name: transferHTTPparsedURL (same as above but takes parsed url)//*//* Description: sends an http request, and returns the output in a //* null terminated string (allocated by function, freed by//* caller). automatically generates host line. if//* no path is given default path is '/' HTTP version 1.1//* is used for everything except "GET"//* //* In: char * request (NULL terminated string, e.g. "GET")//* char * toSend (bytes to be sent AFTER the HOST header)//* int toSendSize (number of bytes in toSend)//* char ** out (output)//* uri_type *URL(parsed url)//*//* Out: HTTP_SUCCESS (on success) , (*out) null terminated string//* //* Return Codes: HTTP_SUCCESS//* Error Codes: UPNP_E_OUTOF_MEMORY//* UPNP_E_READ_SOCKET//* UPNP_E_WRITE_SOCKET//* UPNP_E_OUTOF_SOCKET//* UPNP_E_SOCKET_CONNECT//* //* Example: Suppose parsed_url is the parsed form of //* "http://localhost:80"//* transferHTTP("GET","\r\n",2,&temp,//* &parsed_url);//* ------------------------------------------------------------//* A TCP conneciton is opened to localhost:80.//* The following is sent: //* "GET /foo?silly HTTP/1.1\r\nHOST: localhost:80\r\n\r\n"//*************************************************************************int transferHTTPparsedURL( char * request, char * toSend, int toSendSize, char **out, uri_type *URL){ uri_type parsed_url=(*URL); int request_length=0; int host_length=0; char * message=NULL; char * message_finger=NULL; int client_socket=0; char temp_path='/'; int return_code=HTTP_SUCCESS; int message_size=0; if (token_string_casecmp(&parsed_url.scheme,"http")) { return UPNP_E_INVALID_URL; } if (parsed_url.hostport.text.size==0) { return UPNP_E_INVALID_URL; } if (parsed_url.pathquery.size==0) { parsed_url.pathquery.size=1; parsed_url.pathquery.buff=&temp_path; } //request_length="(request)<sp>(path)<sp>HTTP/1.1\r\n" request_length=strlen(request) + 1 + parsed_url.pathquery.size + 8 +1 + 2; //host_length = "HOST:<sp>(host:port)\r\n" host_length = 6 + parsed_url.hostport.text.size +2; message_size=request_length+host_length+toSendSize; message = (char * ) malloc(message_size); if (message==NULL) return UPNP_E_OUTOF_MEMORY; message_finger=message; sprintf(message, "%s ",request); message_finger+=strlen(request)+1; memcpy(message_finger,parsed_url.pathquery.buff, parsed_url.pathquery.size); message_finger+=parsed_url.pathquery.size; //hack to force server to return content length if (!strcasecmp(request,"GET")) memcpy(message_finger," HTTP/1.0\r\nHOST: ",17); else memcpy(message_finger," HTTP/1.1\r\nHOST: ",17); message_finger+=17; memcpy(message_finger,parsed_url.hostport.text.buff, parsed_url.hostport.text.size); message_finger+=parsed_url.hostport.text.size; memcpy(message_finger,"\r\n",2); message_finger+=2; memcpy(message_finger,toSend,toSendSize); //set up tcp connection if ( (client_socket=socket(AF_INET,SOCK_STREAM,0))==-1) { free(message); DBGONLY(UpnpPrintf(UPNP_CRITICAL,API,__FILE__,__LINE__,"OUT OF SOCKET")); return UPNP_E_OUTOF_SOCKET; } if (connect(client_socket,(struct sockaddr*) & parsed_url.hostport.IPv4address,sizeof(struct sockaddr))==-1) { free(message); close(client_socket); DBGONLY(UpnpPrintf(UPNP_CRITICAL,API,__FILE__,__LINE__,"CONNECT ERROR")); return UPNP_E_SOCKET_CONNECT; } if ( write_bytes(client_socket,message,message_size,RESPONSE_TIMEOUT)==-1) { free(message); close(client_socket); DBGONLY(UpnpPrintf(UPNP_CRITICAL,API,__FILE__,__LINE__,"WRITE ERROR")); return UPNP_E_SOCKET_WRITE; } free(message); return_code=read_http_response(client_socket,out,RESPONSE_TIMEOUT); close(client_socket); return return_code;}void free_http_headers(http_header * list){ http_header * next; while (list) { next=list->next; free(list); list=next; }}void free_http_message(http_message * message){ free_http_headers(message->header_list);}DBGONLY(void print_http_response(http_message * message, Dbg_Level level, Dbg_Module module, char *DbgFileName, int DbgLineNo){ FILE *fd = GetDebugFile(level,module); http_header *list=message->header_list; if (!fd) return; if (DbgFileName) { //get lock pthread_mutex_lock(&GlobalDebugMutex); UpnpDisplayFileAndLine(fd,DbgFileName,DbgLineNo); } fprintf(fd,"------------------------------------\n"); fprintf(fd,"RESPONSE: "); print_status_line(&message->status,level,module,NULL,0); fprintf(fd,"HEADERS: \n"); while (list) { print_token(&list->header,level,module,NULL,0); print_token(&list->value,level,module,NULL,0); list=list->next; } fprintf(fd,"CONTENT: \n"); print_token(&message->content,level,module,NULL,0); fprintf(fd,"-----------------------------------\n"); fflush(fd); if (DbgFileName) { pthread_mutex_unlock(&GlobalDebugMutex); }})DBGONLY(void print_http_request( http_message * message,Dbg_Level level, Dbg_Module module, char *DbgFileName, int DbgLineNo){ FILE *fd = GetDebugFile(level,module); http_header *list=message->header_list; if (!
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -