bool husthttp_t::open2 ( std::string & method, std::string & path, std::string & query_string, std::string & data, int conn_timeout, int recv_timeout ) { if ( unlikely ( ! m_h ) ) { m_h = http_create (); if ( ! m_h ) { return false; } } if ( unlikely ( method.empty () || path.empty () ) ) { return false; } if ( m_method.compare ( method ) != 0 ) { m_method = method; } if ( m_path.compare ( path ) != 0 ) { m_path = path; } if ( query_string.size () <= 0 ) { m_query_string.resize ( 0 ); } else if ( m_query_string.compare ( query_string ) != 0 ) { m_query_string = query_string; } m_data.resize ( 0 ); if ( data.size () > 0 ) { m_data = data; } if ( conn_timeout > 0 ) { m_conn_timeout = conn_timeout; } if ( recv_timeout > 0 ) { m_recv_timeout = recv_timeout; } return true; }
int mfconn_api_device_get_status(mfconn * conn, uint64_t * revision) { const char *api_call; int retval; mfhttp *http; int i; if (conn == NULL) return -1; for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { api_call = mfconn_create_signed_get(conn, 0, "device/get_status.php", "?response_format=json"); if (api_call == NULL) { fprintf(stderr, "mfconn_create_signed_get failed\n"); return -1; } http = http_create(); if (mfconn_get_http_flags(conn) & HTTP_FLAG_LAZY_SSL) { http_set_connect_flags(http, HTTP_FLAG_LAZY_SSL); } http_set_data_handler(http, _decode_device_get_status, (void *)revision); retval = http_get_buf(http, api_call); http_destroy(http); mfconn_update_secret_key(conn); free((void *)api_call); if (retval != 127 && retval != 28) break; // if there was either a curl timeout or a token error, get a new // token and try again // // on a curl timeout we get a new token because it is likely that we // lost signature synchronization (we don't know whether the server // accepted or rejected the last call) fprintf(stderr, "got error %d - negotiate a new token\n", retval); retval = mfconn_refresh_token(conn); if (retval != 0) { fprintf(stderr, "failed to get a new token\n"); break; } } return retval; }
/** Process an incoming request @returns nothing **/ void http_response(SOCKET fd) { HTTP *http = http_create(fd); size_t len; int content_length = 0; char *user_agent = NULL; char *host = NULL; int keep_alive = 0; char *connection = NULL; char *accept = NULL; struct s_map { char *name; enum {INTEGER,STRING} type; void *value; size_t sz; } map[] = { {"Content-Length", INTEGER, (void*)&content_length, 0}, {"Host", STRING, (void*)&host, 0}, {"Keep-Alive", INTEGER, (void*)&keep_alive, 0}, {"Connection", STRING, (void*)&connection, 0}, {"Accept", STRING, (void*)&accept, 0}, }; while ( (int)(len=recv_data(fd,http->query,sizeof(http->query)))>0 ) { /* first term is always the request */ char *request = http->query; char method[32]; char uri[1024]; char version[32]; char *p = strchr(http->query,'\r'); int v; /* initialize the response */ http_reset(http); /* read the request string */ if (sscanf(request,"%s %s %s",method,uri,version)!=3) { http_status(http,HTTP_BADREQUEST); http_format(http,HTTP_BADREQUEST); http_type(http,"text/html"); http_send(http); break; } /* read the rest of the header */ while (p!=NULL && (p=strchr(p,'\r'))!=NULL) { *p = '\0'; p+=2; for ( v=0 ; v<sizeof(map)/sizeof(map[0]) ; v++ ) { if (map[v].sz==0) map[v].sz = strlen(map[v].name); if (strnicmp(map[v].name,p,map[v].sz)==0 && strncmp(p+map[v].sz,": ",2)==0) { if (map[v].type==INTEGER) { *(int*)(map[v].value) = atoi(p+map[v].sz+2); break; } else if (map[v].type==STRING) { *(char**)map[v].value = p+map[v].sz+2; break; } } } } output_verbose("%s (host='%s', len=%d)",http->query,host?host:"???",content_length); /* reject anything but a GET */ if (stricmp(method,"GET")!=0) { http_status(http,HTTP_METHODNOTALLOWED); http_format(http,HTTP_METHODNOTALLOWED); http_type(http,"text/html"); /* technically, we should add an Allow entry to the response header */ http_send(http); break; } /* handle request */ if ( strcmp(uri,"/favicon.ico")==0 ) { if ( http_favicon(http) ) http_status(http,HTTP_OK); else http_status(http,HTTP_NOTFOUND); http_send(http); } else { static struct s_map { char *path; int (*request)(HTTP*,char*); char *success; char *failure; } map[] = { /* this is the map of recognize request types */ {"/xml/", http_xml_request, HTTP_OK, HTTP_NOTFOUND}, {"/gui/", http_gui_request, HTTP_OK, HTTP_NOTFOUND}, {"/output/", http_output_request, HTTP_OK, HTTP_NOTFOUND}, {"/action/", http_action_request, HTTP_ACCEPTED,HTTP_NOTFOUND}, {"/rt/", http_get_rt, HTTP_OK, HTTP_NOTFOUND}, {"/perl/", http_run_perl, HTTP_OK, HTTP_NOTFOUND}, {"/gnuplot/", http_run_gnuplot, HTTP_OK, HTTP_NOTFOUND}, {"/java/", http_run_java, HTTP_OK, HTTP_NOTFOUND}, {"/python/", http_run_python, HTTP_OK, HTTP_NOTFOUND}, {"/r/", http_run_r, HTTP_OK, HTTP_NOTFOUND}, {"/scilab/", http_run_scilab, HTTP_OK, HTTP_NOTFOUND}, {"/octave/", http_run_octave, HTTP_OK, HTTP_NOTFOUND}, }; int n; for ( n=0 ; n<sizeof(map)/sizeof(map[0]) ; n++ ) { size_t len = strlen(map[n].path); if (strncmp(uri,map[n].path,len)==0) { if ( map[n].request(http,uri+len) ) http_status(http,map[n].success); else http_status(http,map[n].failure); http_send(http); goto Next; } } } /* deprecated XML usage */ if (strncmp(uri,"/",1)==0 ) { if ( http_xml_request(http,uri+1) ) { output_warning("deprecate XML usage in request '%s'", uri); http_status(http,HTTP_OK); } else http_status(http,HTTP_NOTFOUND); http_send(http); } else { http_status(http,HTTP_NOTFOUND); http_format(http,HTTP_NOTFOUND); http_type(http,"text/html"); http_send(http); } /* keep-alive not desired*/ Next: if (connection && stricmp(connection,"close")==0) break; } http_close(http); output_verbose("socket %d closed",http->s); }
int mfconn_api_file_get_links(mfconn * conn, mffile * file, const char *quickkey, enum mfconn_file_link_type link_mask) { const char *api_call; int retval; int len; mfhttp *http; int i; if (conn == NULL) return -1; if (file == NULL) return -1; if (quickkey == NULL) return -1; len = strlen(quickkey); // key must either be 11 or 15 chars if (len != 11 && len != 15) return -1; for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { api_call = mfconn_create_signed_get(conn, 0, "file/get_links.php", "?quick_key=%s" "&link_type=%s" "&response_format=json", quickkey, mfconn_file_link_types[link_mask]); if (api_call == NULL) { fprintf(stderr, "mfconn_create_signed_get failed\n"); return -1; } http = http_create(); if (mfconn_get_http_flags(conn) & HTTP_FLAG_LAZY_SSL) { http_set_connect_flags(http, HTTP_FLAG_LAZY_SSL); } http_set_data_handler(http, _decode_file_get_links, file); retval = http_get_buf(http, api_call); http_destroy(http); mfconn_update_secret_key(conn); free((void *)api_call); if (retval != 127 && retval != 28) break; // if there was either a curl timeout or a token error, get a new // token and try again // // on a curl timeout we get a new token because it is likely that we // lost signature synchronization (we don't know whether the server // accepted or rejected the last call) fprintf(stderr, "got error %d - negotiate a new token\n", retval); retval = mfconn_refresh_token(conn); if (retval != 0) { fprintf(stderr, "failed to get a new token\n"); break; } } return retval; }
int mfconn_api_folder_get_info(mfconn * conn, mffolder * folder, const char *folderkey) { const char *api_call; int retval; mfhttp *http; int i; if (conn == NULL) return -1; if (folder == NULL) return -1; // key must either be 13 chars or NULL if (folderkey != NULL && strlen(folderkey) != 13) { return -1; } for (i = 0; i < mfconn_get_max_num_retries(conn); i++) { if (folderkey == NULL) { api_call = mfconn_create_signed_get(conn, 0, "folder/get_info.php", "?response_format=json"); } else { api_call = mfconn_create_signed_get(conn, 0, "folder/get_info.php", "?folder_key=%s" "&response_format=json", folderkey); } if (api_call == NULL) { fprintf(stderr, "mfconn_create_signed_get failed\n"); return -1; } http = http_create(); if (mfconn_get_http_flags(conn) & HTTP_FLAG_LAZY_SSL) { http_set_connect_flags(http, HTTP_FLAG_LAZY_SSL); } http_set_data_handler(http, _decode_folder_get_info, folder); retval = http_get_buf(http, api_call); http_destroy(http); mfconn_update_secret_key(conn); free((void *)api_call); if (retval != 127 && retval != 28) break; // if there was either a curl timeout or a token error, get a new // token and try again // // on a curl timeout we get a new token because it is likely that we // lost signature synchronization (we don't know whether the server // accepted or rejected the last call) fprintf(stderr, "got error %d - negotiate a new token\n", retval); retval = mfconn_refresh_token(conn); if (retval != 0) { fprintf(stderr, "failed to get a new token\n"); break; } } return retval; }
bool husthttp_t::open ( const char * method, const char * path, const char * query_string, const char * data, size_t data_len, int conn_timeout, int recv_timeout ) { if ( unlikely ( ! m_h ) ) { m_h = http_create (); if ( ! m_h ) { return false; } } if ( unlikely ( ! method || ! path ) ) { return false; } if ( m_method.compare ( method ) != 0 ) { m_method = method; } if ( m_path.compare ( path ) != 0 ) { m_path = path; } if ( ! query_string ) { m_query_string.resize ( 0 ); } else if ( m_query_string.compare ( query_string ) != 0 ) { m_query_string = query_string; } m_data.resize ( 0 ); if ( data_len > 0 ) { m_data.assign (( const char * ) data, ( const char * ) ( data + data_len )); } if ( conn_timeout > 0 ) { m_conn_timeout = conn_timeout; } if ( recv_timeout > 0 ) { m_recv_timeout = recv_timeout; } return true; }
void http_response(SOCKET fd) { HTTP *http = http_create(fd); size_t len; int content_length = 0; char *user_agent = NULL; char *host = NULL; int keep_alive = 0; char *connection = NULL; char *accept = NULL; struct s_map { char *name; enum {INTEGER,STRING} type; void *value; int sz; } map[] = { {"Content-Length", INTEGER, (void*)&content_length, 0}, {"Host", STRING, (void*)&host, 0}, {"Keep-Alive", INTEGER, (void*)&keep_alive, 0}, {"Connection", STRING, (void*)&connection, 0}, {"Accept", STRING, (void*)&accept, 0}, }; while ( (int)(len=recv_data(fd,http->query,sizeof(http->query)))>0 ) { /* first term is always the request */ char *request = http->query; char method[32]; char uri[1024]; char version[32]; char *p = strchr(http->query,'\r'); int v; /* read the request string */ if (sscanf(request,"%s %s %s",method,uri,version)!=3) { http_status(http,HTTP_BADREQUEST); http_format(http,HTTP_BADREQUEST); http_type(http,"text/html"); http_send(http); break; } /* read the rest of the header */ while (p!=NULL && (p=strchr(p,'\r'))!=NULL) { *p = '\0'; p+=2; for ( v=0 ; v<sizeof(map)/sizeof(map[0]) ; v++ ) { if (map[v].sz==0) map[v].sz = strlen(map[v].name); if (strnicmp(map[v].name,p,map[v].sz)==0 && strncmp(p+map[v].sz,": ",2)==0) { if (map[v].type==INTEGER) { *(int*)(map[v].value) = atoi(p+map[v].sz+2); break; } else if (map[v].type==STRING) { *(char**)map[v].value = p+map[v].sz+2; break; } } } } output_verbose("%s (host='%s', len=%d)",http->query,host?host:"???",content_length); /* reject anything but a GET */ if (stricmp(method,"GET")!=0) { http_status(http,HTTP_METHODNOTALLOWED); http_format(http,HTTP_METHODNOTALLOWED); http_type(http,"text/html"); /* technically, we should add an Allow entry to the response header */ http_send(http); break; } /* handle request */ if (strncmp(uri,"/gui/",5)==0 ) { if ( http_gui_request(http,uri+5) ) http_status(http,HTTP_OK); else http_status(http,HTTP_NOTFOUND); http_send(http); } else if (strncmp(uri,"/output/",8)==0 ) { if ( http_output_request(http,uri+8) ) http_status(http,HTTP_OK); else http_status(http,HTTP_NOTFOUND); http_send(http); } else if (strncmp(uri,"/action/",8)==0) { if ( http_action_request(http,uri+8) ) http_status(http,HTTP_ACCEPTED); else http_status(http,HTTP_NOTFOUND); http_send(http); } else if ( strcmp(uri,"/favicon.ico")==0 ) { if ( http_favicon(http) ) http_status(http,HTTP_OK); else http_status(http,HTTP_NOTFOUND); http_send(http); } else if (strncmp(uri,"/",1)==0 ) { if ( http_xml_request(http,uri+1) ) http_status(http,HTTP_OK); else http_status(http,HTTP_NOTFOUND); http_send(http); } else { http_status(http,HTTP_NOTFOUND); http_format(http,HTTP_NOTFOUND); http_type(http,"text/html"); http_send(http); } /* keep-alive not desired*/ if (connection && stricmp(connection,"close")==0) break; } http_close(http); output_verbose("socket %d closed",http->s); }