/*! * \brief Initialize the global XML document. Allocate buffers for the XML * document. */ static UPNP_INLINE void glob_alias_init(void) { struct xml_alias_t *alias = &gAliasDoc; membuffer_init(&alias->doc); membuffer_init(&alias->name); alias->ct = NULL; alias->last_modified = 0; }
/* Allocates curl_state data needed for a new Session object. */ VALUE session_alloc(VALUE klass) { struct curl_state* curl; VALUE obj = Data_Make_Struct(klass, struct curl_state, NULL, session_free, curl); membuffer_init( &curl->header_buffer ); membuffer_init( &curl->body_buffer ); cs_list_append(curl); return obj; }
ib_status_t ib_kvstore_riak_set_bucket_property_str( ib_kvstore_t *kvstore, const char *property, const char *value) { assert(kvstore); assert(property); assert(value); const char *post_fmt = "{\"props\":{\"%s\":\"%s\"}}"; membuffer_t request; ib_status_t rc; membuffer_init(kvstore, &request); request.read = 0; request.size = strlen(property) + /* Property length. */ strlen(value) + /* Value length. */ strlen(post_fmt) - 4; /* post_fmt - %s and %s. */ /* Note: size+1 so we can use sprintf below. */ request.buffer = kvmalloc(kvstore, request.size+1); if (!request.buffer) { return IB_EALLOC; } sprintf(request.buffer, post_fmt, property, value); rc = ib_kvstore_riak_set_bucket_property(kvstore, &request); cleanup_membuffer(&request); return rc; }
int web_server_init() { int ret = 0; if (bWebServerState == WEB_SERVER_DISABLED) { /* decode media list */ media_list_init(); membuffer_init(&gDocumentRootDir); glob_alias_init(); pVirtualDirList = NULL; /* Initialize callbacks */ virtualDirCallback.get_info = NULL; virtualDirCallback.open = NULL; virtualDirCallback.read = NULL; virtualDirCallback.write = NULL; virtualDirCallback.seek = NULL; virtualDirCallback.close = NULL; if (ithread_mutex_init(&gWebMutex, NULL) == -1) ret = UPNP_E_OUTOF_MEMORY; else bWebServerState = WEB_SERVER_ENABLED; } return ret; }
void gena_process_unsubscribe_request( SOCKINFO *info, http_message_t *request) { Upnp_SID sid; service_info *service; struct Handle_Info *handle_info; UpnpDevice_Handle device_handle; memptr temp_hdr; membuffer event_url_path; /* if a CALLBACK or NT header is present, then it is an error */ if( httpmsg_find_hdr( request, HDR_CALLBACK, NULL ) != NULL || httpmsg_find_hdr( request, HDR_NT, NULL ) != NULL ) { error_respond( info, HTTP_BAD_REQUEST, request ); return; } /* get SID */ if( httpmsg_find_hdr( request, HDR_SID, &temp_hdr ) == NULL || temp_hdr.length > SID_SIZE ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); return; } memcpy( sid, temp_hdr.buf, temp_hdr.length ); sid[temp_hdr.length] = '\0'; /* lookup service by eventURL */ membuffer_init( &event_url_path ); if( membuffer_append( &event_url_path, request->uri.pathquery.buff, request->uri.pathquery.size ) != 0 ) { error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); return; } HandleLock(); if( GetDeviceHandleInfoForPath(event_url_path.buf, info->foreign_sockaddr.ss_family, &device_handle, &handle_info, &service) != HND_DEVICE ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); membuffer_destroy( &event_url_path ); HandleUnlock(); return; } membuffer_destroy( &event_url_path ); /* validate service */ if( service == NULL || !service->active || GetSubscriptionSID( sid, service ) == NULL ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); HandleUnlock(); return; } RemoveSubscriptionSID(sid, service); error_respond(info, HTTP_OK, request); /* success */ HandleUnlock(); }
int web_server_set_alias(const char *alias_name, const char *alias_content, size_t alias_content_length, time_t last_modified) { int ret_code; struct xml_alias_t alias; alias_release(&gAliasDoc); if (alias_name == NULL) { /* don't serve aliased doc anymore */ return 0; } assert(alias_content != NULL); membuffer_init(&alias.doc); membuffer_init(&alias.name); alias.ct = NULL; do { /* insert leading /, if missing */ if (*alias_name != '/') if (membuffer_assign_str(&alias.name, "/") != 0) break; /* error; out of mem */ ret_code = membuffer_append_str(&alias.name, alias_name); if (ret_code != 0) break; /* error */ if ((alias.ct = (int *)malloc(sizeof(int))) == NULL) break; /* error */ *alias.ct = 1; membuffer_attach(&alias.doc, (char *)alias_content, alias_content_length); alias.last_modified = last_modified; /* save in module var */ ithread_mutex_lock(&gWebMutex); gAliasDoc = alias; ithread_mutex_unlock(&gWebMutex); return 0; } while (FALSE); /* error handler */ /* free temp alias */ membuffer_destroy(&alias.name); membuffer_destroy(&alias.doc); free(alias.ct); return UPNP_E_OUTOF_MEMORY; }
void membuffer_destroy(membuffer *m) { if (m == NULL) { return; } if(m->buf != NULL) tls_mem_free(m->buf); membuffer_init(m); }
/*! * \brief Returns OK message in the case of a subscription request. * * \return UPNP_E_SUCCESS if successful, otherwise the appropriate error code. */ static int respond_ok( /*! [in] Socket connection of request. */ SOCKINFO *info, /*! [in] Accepted duration. */ int time_out, /*! [in] Accepted subscription. */ subscription *sub, /*! [in] Http request. */ http_message_t *request) { int major; int minor; membuffer response; int return_code; char timeout_str[100]; int upnp_timeout = UPNP_TIMEOUT; int rc = 0; http_CalcResponseVersion( request->major_version, request->minor_version, &major, &minor ); if( time_out >= 0 ) { rc = snprintf( timeout_str, sizeof ( timeout_str ), "TIMEOUT: Second-%d", time_out ); } else { memset( timeout_str, 0, sizeof( timeout_str ) ); strncpy( timeout_str, "TIMEOUT: Second-infinite", sizeof ( timeout_str ) - 1); } if (rc < 0 || (unsigned int) rc >= sizeof ( timeout_str ) ) { error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); return UPNP_E_OUTOF_MEMORY; } membuffer_init( &response ); response.size_inc = 30; if( http_MakeMessage( &response, major, minor, "R" "D" "S" "N" "Xc" "ssc" "scc", HTTP_OK, (off_t)0, X_USER_AGENT, "SID: ", sub->sid, timeout_str ) != 0 ) { membuffer_destroy( &response ); error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); return UPNP_E_OUTOF_MEMORY; } return_code = http_SendMessage( info, &upnp_timeout, "b", response.buf, response.length ); membuffer_destroy( &response ); return return_code; }
/************************************************************************ * Function : membuffer_destroy * * Parameters : * INOUT membuffer* m ; buffer to be destroyed * * Description : Free's memory allocated for membuffer* m. * * Return : void ; * * Note : ************************************************************************/ void membuffer_destroy( INOUT membuffer * m ) { if( m == NULL ) { return; } free( m->buf ); membuffer_init( m ); }
/*! * \brief Sends the UNSUBCRIBE gena request and recieves the response from the * device and returns it as a parameter. * * \returns 0 if successful, otherwise returns the appropriate error code. */ static int gena_unsubscribe( /*! [in] Event URL of the service. */ IN const UpnpString *url, /*! [in] The subcription ID. */ IN const UpnpString *sid, /*! [out] The UNSUBCRIBE response from the device. */ OUT http_parser_t *response ) { int return_code; uri_type dest_url; membuffer request; /* parse url */ return_code = http_FixStrUrl( UpnpString_get_String(url), UpnpString_get_Length(url), &dest_url); if (return_code != 0) { return return_code; } /* make request msg */ membuffer_init(&request); request.size_inc = 30; return_code = http_MakeMessage( &request, 1, 1, "q" "ssc" "Uc", HTTPMETHOD_UNSUBSCRIBE, &dest_url, "SID: ", UpnpString_get_String(sid)); /* Not able to make the message so destroy the existing buffer */ if (return_code != 0) { membuffer_destroy(&request); return return_code; } /* send request and get reply */ return_code = http_RequestAndResponse( &dest_url, request.buf, request.length, HTTPMETHOD_UNSUBSCRIBE, HTTP_DEFAULT_TIMEOUT, response); membuffer_destroy(&request); if (return_code != 0) { httpmsg_destroy(&response->msg); } if (return_code == 0 && response->msg.status_code != HTTP_OK) { return_code = UPNP_E_UNSUBSCRIBE_UNACCEPTED; httpmsg_destroy(&response->msg); } return return_code; }
MemBuffer * membuffer_new_from_buffer_dup (DWORD addr, Buffer *buf) { MemBuffer *membuffer; if ((membuffer = malloc(sizeof(MemBuffer))) == NULL) return NULL; membuffer_init (membuffer, addr, buffer_dup(buf)); return membuffer; }
/**************************************************************************** * Function : send_var_query_response * * Parameters : * IN SOCKINFO *info : socket info * IN const char* var_value : value of the state variable * IN http_message_t* hmsg : HTTP request * * Description : This function sends response of get var status * * Return : void * * Note : ****************************************************************************/ static UPNP_INLINE void send_var_query_response( IN SOCKINFO * info, IN const char *var_value, IN http_message_t * hmsg ) { off_t content_length; int timeout_secs = SOAP_TIMEOUT; int major; int minor; const char *start_body = "<s:Envelope " "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" "<s:Body>\n" "<u:QueryStateVariableResponse " "xmlns:u=\"urn:schemas-upnp-org:control-1-0\">\n" "<return>"; const char *end_body = "</return>\n" "</u:QueryStateVariableResponse>\n" "</s:Body>\n" "</s:Envelope>\n"; membuffer response; http_CalcResponseVersion( hmsg->major_version, hmsg->minor_version, &major, &minor ); content_length = strlen( start_body ) + strlen( var_value ) + strlen( end_body ); // make headers membuffer_init( &response ); if (http_MakeMessage( &response, major, minor, "RNsDsSXcc" "sss", HTTP_OK, content_length, ContentTypeHeader, "EXT:\r\n", X_USER_AGENT, start_body, var_value, end_body ) != 0 ) { membuffer_destroy( &response ); return; // out of mem } // send msg http_SendMessage( info, &timeout_secs, "b", response.buf, response.length ); membuffer_destroy( &response ); }
MemBuffer * membuffer_new (DWORD addr, unsigned char *code, int size) { MemBuffer *membuffer; if ((membuffer = malloc(sizeof(MemBuffer))) == NULL) return NULL; membuffer_init (membuffer, addr, buffer_new_from_ptr(code, size) ); return membuffer; }
/*! * \brief Function to Notify a particular subscription of a particular event. * * In general the service should NOT be blocked around this call (this may * cause deadlock with a client). * * NOTIFY http request is sent and the reply is processed. * * \return GENA_SUCCESS if the event was delivered, otherwise returns the * appropriate error code. */ static int genaNotify( /*! [in] Null terminated, includes all headers (including \\r\\n) except SID and SEQ. */ char *headers, /*! [in] The evented XML. */ char *propertySet, /*! [in] subscription to be Notified, assumes this is valid for life of function. */ subscription *sub) { size_t i; membuffer mid_msg; uri_type *url; http_parser_t response; int return_code = -1; membuffer_init(&mid_msg); if (http_MakeMessage(&mid_msg, 1, 1, "s" "ssc" "sdcc", headers, "SID: ", sub->sid, "SEQ: ", sub->ToSendEventKey) != 0) { membuffer_destroy(&mid_msg); return UPNP_E_OUTOF_MEMORY; } /* send a notify to each url until one goes thru */ for (i = 0; i < sub->DeliveryURLs.size; i++) { url = &sub->DeliveryURLs.parsedURLs[i]; return_code = notify_send_and_recv( url, &mid_msg, propertySet, &response); if (return_code == UPNP_E_SUCCESS) break; } membuffer_destroy(&mid_msg); if (return_code == UPNP_E_SUCCESS) { if (response.msg.status_code == HTTP_OK) return_code = GENA_SUCCESS; else { if (response.msg.status_code == HTTP_PRECONDITION_FAILED) /*Invalid SID gets removed */ return_code = GENA_E_NOTIFY_UNACCEPTED_REMOVE_SUB; else return_code = GENA_E_NOTIFY_UNACCEPTED; } httpmsg_destroy(&response.msg); } return return_code; }
/************************************************************************ * Function : gena_unsubscribe * * Parameters: * IN char *url: Event URL of the service * IN char *sid: The subcription ID. * OUT http_parser_t* response: The UNSUBCRIBE response from the device * * Description: * This function sends the UNSUBCRIBE gena request and recieves the * response from the device and returns it as a parameter * * Returns: int * return 0 if successful else returns appropriate error ***************************************************************************/ static int gena_unsubscribe( IN char *url, IN char *sid, OUT http_parser_t * response ) { int return_code; uri_type dest_url; membuffer request; // parse url return_code = http_FixStrUrl( url, strlen( url ), &dest_url ); if( return_code != 0 ) { return return_code; } // make request msg membuffer_init( &request ); request.size_inc = 30; return_code = http_MakeMessage( &request, 1, 1, "q" "ssc" "U" "c", HTTPMETHOD_UNSUBSCRIBE, &dest_url, "SID: ", sid ); //Not able to make the message so destroy the existing buffer if( return_code != 0 ) { membuffer_destroy( &request ); return return_code; } // send request and get reply return_code = http_RequestAndResponse( &dest_url, request.buf, request.length, HTTPMETHOD_UNSUBSCRIBE, HTTP_DEFAULT_TIMEOUT, response ); membuffer_destroy( &request ); if( return_code != 0 ) httpmsg_destroy( &response->msg ); if( return_code == 0 && response->msg.status_code != HTTP_OK ) { return_code = UPNP_E_UNSUBSCRIBE_UNACCEPTED; httpmsg_destroy( &response->msg ); } return return_code; }
ib_status_t ib_kvstore_riak_set_bucket_property_int( ib_kvstore_t *kvstore, const char *property, int value) { assert(kvstore); assert(property); const char *post_fmt = "{\"props\":{\"%s\":%d}}"; membuffer_t request; const int digits = 6; size_t size; ib_status_t rc; if (value < 0) { return IB_EINVAL; } /* Digits is greater than 6, so we can't represent it in our buffer. */ if (value > 999999) { return IB_EINVAL; } membuffer_init(kvstore, &request); request.read = 0; size = strlen(property) + digits + strlen(post_fmt)-4; request.buffer = kvmalloc(kvstore, size+1); if (!request.buffer) { return IB_EALLOC; } request.size = sprintf(request.buffer, post_fmt, property, value); rc = ib_kvstore_riak_set_bucket_property(kvstore, &request); cleanup_membuffer(&request); return rc; }
/*! * \brief Sends SOAP error response. */ static void send_error_response( /*! [in] Socket info. */ IN SOCKINFO *info, /*! [in] Error code. */ IN int error_code, /*! [in] Error message. */ IN const char *err_msg, /*! [in] HTTP request. */ IN http_message_t *hmsg) { off_t content_length; int timeout_secs = SOAP_TIMEOUT; int major; int minor; const char *start_body = "<?xml version=\"1.0\"?>\n" "<s:Envelope " "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\" " "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" "<s:Body>\n" "<s:Fault>\n" "<faultcode>s:Client</faultcode>\n" "<faultstring>UPnPError</faultstring>\n" "<detail>\n" "<UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">\n" "<errorCode>"; const char *mid_body = "</errorCode>\n" "<errorDescription>"; const char *end_body = "</errorDescription>\n" "</UPnPError>\n" "</detail>\n" "</s:Fault>\n" "</s:Body>\n" "</s:Envelope>\n"; char err_code_str[30]; membuffer headers; memset(err_code_str, 0, sizeof(err_code_str)); snprintf(err_code_str, sizeof(err_code_str), "%d", error_code); /* calc body len */ content_length = (off_t) (strlen(start_body) + strlen(err_code_str) + strlen(mid_body) + strlen(err_msg) + strlen(end_body)); http_CalcResponseVersion(hmsg->major_version, hmsg->minor_version, &major, &minor); /* make headers */ membuffer_init(&headers); if (http_MakeMessage(&headers, major, minor, "RNsDsSXcc" "sssss", 500, content_length, ContentTypeHeader, "EXT:\r\n", X_USER_AGENT, start_body, err_code_str, mid_body, err_msg, end_body) != 0) { membuffer_destroy(&headers); /* out of mem */ return; } /* send err msg */ http_SendMessage(info, &timeout_secs, "b", headers.buf, headers.length); membuffer_destroy(&headers); }
/*! * \brief Sends the notify message and returns a reply. * * \return on success returns UPNP_E_SUCCESS, otherwise returns a UPNP error. * * \note called by genaNotify */ static UPNP_INLINE int notify_send_and_recv( /*! [in] subscription callback URL (URL of the control point). */ uri_type *destination_url, /*! [in] Common HTTP headers. */ membuffer *mid_msg, /*! [in] The evented XML. */ char *propertySet, /*! [out] The response from the control point. */ http_parser_t *response) { uri_type url; SOCKET conn_fd; membuffer start_msg; int ret_code; int err_code; int timeout; SOCKINFO info; const char *CRLF = "\r\n"; /* connect */ UpnpPrintf(UPNP_ALL, GENA, __FILE__, __LINE__, "gena notify to: %.*s\n", (int)destination_url->hostport.text.size, destination_url->hostport.text.buff); conn_fd = http_Connect(destination_url, &url); if (conn_fd < 0) /* return UPNP error */ return UPNP_E_SOCKET_CONNECT; ret_code = sock_init(&info, conn_fd); if (ret_code) { sock_destroy(&info, SD_BOTH); return ret_code; } /* make start line and HOST header */ membuffer_init(&start_msg); if (http_MakeMessage( &start_msg, 1, 1, "q" "s", HTTPMETHOD_NOTIFY, &url, mid_msg->buf) != 0) { membuffer_destroy(&start_msg); sock_destroy(&info, SD_BOTH); return UPNP_E_OUTOF_MEMORY; } timeout = GENA_NOTIFICATION_SENDING_TIMEOUT; /* send msg (note: end of notification will contain "\r\n" twice) */ ret_code = http_SendMessage(&info, &timeout, "bbb", start_msg.buf, start_msg.length, propertySet, strlen(propertySet), CRLF, strlen(CRLF)); if (ret_code) { membuffer_destroy(&start_msg); sock_destroy(&info, SD_BOTH); return ret_code; } timeout = GENA_NOTIFICATION_ANSWERING_TIMEOUT; ret_code = http_RecvMessage(&info, response, HTTPMETHOD_NOTIFY, &timeout, &err_code); if (ret_code) { membuffer_destroy(&start_msg); sock_destroy(&info, SD_BOTH); httpmsg_destroy(&response->msg); return ret_code; } /* should shutdown completely when closing socket */ sock_destroy(&info, SD_BOTH); membuffer_destroy(&start_msg); return UPNP_E_SUCCESS; }
/*! * \brief Sends the SOAP action response. */ static UPNP_INLINE void send_action_response( /*! [in] Socket info. */ SOCKINFO *info, /*! [in] The response document. */ IXML_Document *action_resp, /*! [in] Action request document. */ http_message_t *request) { char *xml_response = NULL; membuffer headers; int major, minor; int err_code; off_t content_length; int ret_code; int timeout_secs = SOAP_TIMEOUT; static const char *start_body = "<?xml version=\"1.0\"?>" "<s:Envelope xmlns:s=\"http://schemas.xmlsoap." "org/soap/envelope/\" s:encodingStyle=\"http://schemas.xmlsoap." "org/soap/encoding/\"><s:Body>\n"; static const char *end_body = "</s:Body> </s:Envelope>"; /* init */ http_CalcResponseVersion(request->major_version, request->minor_version, &major, &minor); membuffer_init(&headers); err_code = UPNP_E_OUTOF_MEMORY; /* one error only */ /* get xml */ xml_response = ixmlPrintNode((IXML_Node *) action_resp); if (!xml_response) goto error_handler; content_length = (off_t)(strlen(start_body) + strlen(xml_response) + strlen(end_body)); /* make headers */ if (http_MakeMessage(&headers, major, minor, "RNsDsSXcc", HTTP_OK, /* status code */ content_length, ContentTypeHeader, "EXT:\r\n", X_USER_AGENT) != 0) { goto error_handler; } /* send whole msg */ ret_code = http_SendMessage( info, &timeout_secs, "bbbb", headers.buf, headers.length, start_body, strlen(start_body), xml_response, strlen(xml_response), end_body, strlen(end_body)); if (ret_code != 0) { UpnpPrintf(UPNP_INFO, SOAP, __FILE__, __LINE__, "Failed to send response: err code = %d\n", ret_code); } err_code = 0; error_handler: ixmlFreeDOMString(xml_response); membuffer_destroy(&headers); if (err_code != 0) { /* only one type of error to worry about - out of mem */ send_error_response(info, SOAP_ACTION_FAILED, "Out of memory", request); } }
void gena_process_subscription_renewal_request( SOCKINFO *info, http_message_t *request) { Upnp_SID sid; subscription *sub; int time_out = 1801; service_info *service; struct Handle_Info *handle_info; UpnpDevice_Handle device_handle; memptr temp_hdr; membuffer event_url_path; memptr timeout_hdr; /* if a CALLBACK or NT header is present, then it is an error */ if( httpmsg_find_hdr( request, HDR_CALLBACK, NULL ) != NULL || httpmsg_find_hdr( request, HDR_NT, NULL ) != NULL ) { error_respond( info, HTTP_BAD_REQUEST, request ); return; } /* get SID */ if( httpmsg_find_hdr( request, HDR_SID, &temp_hdr ) == NULL || temp_hdr.length > SID_SIZE ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); return; } memcpy( sid, temp_hdr.buf, temp_hdr.length ); sid[temp_hdr.length] = '\0'; /* lookup service by eventURL */ membuffer_init( &event_url_path ); if( membuffer_append( &event_url_path, request->uri.pathquery.buff, request->uri.pathquery.size ) != 0 ) { error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); return; } HandleLock(); if (GetDeviceHandleInfoForPath(event_url_path.buf, info->foreign_sockaddr.ss_family, &device_handle, &handle_info, &service) != HND_DEVICE ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); membuffer_destroy( &event_url_path ); HandleUnlock(); return; } membuffer_destroy( &event_url_path ); /* get subscription */ if( service == NULL || !service->active || ( ( sub = GetSubscriptionSID( sid, service ) ) == NULL ) ) { error_respond( info, HTTP_PRECONDITION_FAILED, request ); HandleUnlock(); return; } UpnpPrintf( UPNP_INFO, GENA, __FILE__, __LINE__, "Renew request: Number of subscriptions already: %d\n " "Max Subscriptions allowed:%d\n", service->TotalSubscriptions, handle_info->MaxSubscriptions ); /* too many subscriptions */ if( handle_info->MaxSubscriptions != -1 && service->TotalSubscriptions > handle_info->MaxSubscriptions ) { error_respond( info, HTTP_INTERNAL_SERVER_ERROR, request ); RemoveSubscriptionSID( sub->sid, service ); HandleUnlock(); return; } /* set the timeout */ if( httpmsg_find_hdr( request, HDR_TIMEOUT, &timeout_hdr ) != NULL ) { if( matchstr( timeout_hdr.buf, timeout_hdr.length, "%iSecond-%d%0", &time_out ) == PARSE_OK ) { /*nothing */ } else if( memptr_cmp_nocase( &timeout_hdr, "Second-infinite" ) == 0 ) { time_out = -1; /* inifinite timeout */ } else { time_out = DEFAULT_TIMEOUT; /* default is > 1800 seconds */ } } /* replace infinite timeout with max timeout, if possible */ if( handle_info->MaxSubscriptionTimeOut != -1 ) { if( time_out == -1 || time_out > handle_info->MaxSubscriptionTimeOut ) { time_out = handle_info->MaxSubscriptionTimeOut; } } if( time_out == -1 ) { sub->expireTime = 0; } else { sub->expireTime = time( NULL ) + time_out; } if( respond_ok( info, time_out, sub, request ) != UPNP_E_SUCCESS ) { RemoveSubscriptionSID( sub->sid, service ); } HandleUnlock(); }
/************************************************************************ * Function : gena_subscribe * * Parameters: * IN char *url: url of service to subscribe * INOUT int* timeout:subscription time desired (in secs) * IN char* renewal_sid:for renewal, this contains a currently h * held subscription SID. For first time * subscription, this must be NULL * OUT char** sid: SID returned by the subscription or renew msg * * Description: * This function subscribes or renew subscription * * Returns: int * return 0 if successful else returns appropriate error ***************************************************************************/ static int gena_subscribe( IN char *url, INOUT int *timeout, IN char *renewal_sid, OUT char **sid ) { int return_code; memptr sid_hdr, timeout_hdr; char timeout_str[25]; membuffer request; uri_type dest_url; http_parser_t response; *sid = NULL; // init // request timeout to string if( ( timeout == NULL ) || ( ( *timeout > 0 ) && ( *timeout < CP_MINIMUM_SUBSCRIPTION_TIME ) ) ) { sprintf( timeout_str, "%d", CP_MINIMUM_SUBSCRIPTION_TIME ); } else if( *timeout >= 0 ) { sprintf( timeout_str, "%d", *timeout ); } else { strcpy( timeout_str, "infinite" ); } // parse url return_code = http_FixStrUrl( url, strlen( url ), &dest_url ); if( return_code != 0 ) { return return_code; } // make request msg membuffer_init( &request ); request.size_inc = 30; if( renewal_sid ) { // renew subscription return_code = http_MakeMessage( &request, 1, 1, "q" "ssc" "ssc" "c", HTTPMETHOD_SUBSCRIBE, &dest_url, "SID: ", renewal_sid, "TIMEOUT: Second-", timeout_str ); } else { // subscribe return_code = http_MakeMessage( &request, 1, 1, "q" "sssdsscc", HTTPMETHOD_SUBSCRIBE, &dest_url, "CALLBACK: <http://", LOCAL_HOST, ":", LOCAL_PORT, "/>\r\n" "NT: upnp:event\r\n" "TIMEOUT: Second-", timeout_str ); } if( return_code != 0 ) { return return_code; } // send request and get reply return_code = http_RequestAndResponse( &dest_url, request.buf, request.length, HTTPMETHOD_SUBSCRIBE, HTTP_DEFAULT_TIMEOUT, &response ); membuffer_destroy( &request ); if( return_code != 0 ) { httpmsg_destroy( &response.msg ); return return_code; } if( response.msg.status_code != HTTP_OK ) { httpmsg_destroy( &response.msg ); return UPNP_E_SUBSCRIBE_UNACCEPTED; } // get SID and TIMEOUT if( httpmsg_find_hdr( &response.msg, HDR_SID, &sid_hdr ) == NULL || sid_hdr.length == 0 || httpmsg_find_hdr( &response.msg, HDR_TIMEOUT, &timeout_hdr ) == NULL || timeout_hdr.length == 0 ) { httpmsg_destroy( &response.msg ); return UPNP_E_BAD_RESPONSE; } // save timeout if( matchstr( timeout_hdr.buf, timeout_hdr.length, "%iSecond-%d%0", timeout ) == PARSE_OK ) { // nothing } else if( memptr_cmp_nocase( &timeout_hdr, "Second-infinite" ) == 0 ) { *timeout = -1; } else { httpmsg_destroy( &response.msg ); return UPNP_E_BAD_RESPONSE; } // save SID *sid = str_alloc( sid_hdr.buf, sid_hdr.length ); if( *sid == NULL ) { httpmsg_destroy( &response.msg ); return UPNP_E_OUTOF_MEMORY; } httpmsg_destroy( &response.msg ); return UPNP_E_SUCCESS; }
static ib_status_t kvset( ib_kvstore_t *kvstore, ib_kvstore_merge_policy_fn_t merge_policy, const ib_kvstore_key_t *key, ib_kvstore_value_t *value, ib_kvstore_cbdata_t *cbdata) { char *url; ib_status_t rc; CURLcode curl_rc; ib_kvstore_riak_server_t *riak; struct curl_slist *header_list = NULL; membuffer_t response; membuffer_t value_buffer; riak_headers_t riak_headers; /* Callback data for the value we are setting. */ membuffer_init(kvstore, &value_buffer); value_buffer.size = value->value_length; value_buffer.buffer = value->value; /* Callback data for reading in the body. */ membuffer_init(kvstore, &response); /* Callback data for storing the CURL headers. */ riak_headers_init(kvstore, &riak_headers); riak = (ib_kvstore_riak_server_t *)kvstore->server; rc = IB_OK; url = build_key_url(kvstore, riak, key); /* Set url. */ curl_rc = curl_easy_setopt(riak->curl, CURLOPT_URL, url); if (curl_rc) { rc = IB_EOTHER; goto exit; } /* Use PUT action. */ curl_rc = curl_easy_setopt(riak->curl, CURLOPT_UPLOAD, 1); if (curl_rc) { rc = IB_EOTHER; goto exit; } curl_rc = curl_easy_setopt(riak->curl, CURLOPT_READDATA, &value_buffer); if (curl_rc) { rc = IB_EOTHER; goto exit; } curl_rc = curl_easy_setopt( riak->curl, CURLOPT_INFILESIZE, value_buffer.size); if (curl_rc) { rc = IB_EOTHER; goto exit; } curl_rc = curl_easy_setopt( riak->curl, CURLOPT_READFUNCTION, membuffer_readfunction); if (curl_rc) { rc = IB_EOTHER; goto exit; } curl_rc = curl_easy_setopt( riak->curl, CURLOPT_WRITEFUNCTION, membuffer_writefunction); if (curl_rc) { rc = IB_EOTHER; goto exit; } curl_rc = curl_easy_setopt(riak->curl, CURLOPT_WRITEDATA, &response); if (curl_rc) { rc = IB_EOTHER; goto exit; } curl_rc = curl_easy_setopt( riak->curl, CURLOPT_HEADERFUNCTION, &riak_header_capture); if (curl_rc) { rc = IB_EOTHER; goto exit; } curl_rc = curl_easy_setopt(riak->curl, CURLOPT_WRITEHEADER, &riak_headers); if (curl_rc) { rc = IB_EOTHER; goto exit; } header_list = build_custom_headers(kvstore, riak, value); if (header_list) { curl_rc = curl_easy_setopt( riak->curl, CURLOPT_HTTPHEADER, header_list); if (curl_rc) { rc = IB_EOTHER; goto exit; } } /* Perform the transaction. */ curl_rc = curl_easy_perform(riak->curl); if (curl_rc) { rc = IB_EOTHER; goto exit; } exit: if (header_list) { curl_slist_free_all(header_list); } if (response.buffer) { kvfree(kvstore, response.buffer); } cleanup_riak_headers(&riak_headers); curl_easy_reset(riak->curl); kvfree(kvstore, url); return rc; }
/*! * \brief Creates a HTTP request packet. Depending on the input parameter, * it either creates a service advertisement request or service shutdown * request etc. */ static void CreateServicePacket( /*! [in] type of the message (Search Reply, Advertisement * or Shutdown). */ int msg_type, /*! [in] ssdp type. */ const char *nt, /*! [in] unique service name ( go in the HTTP Header). */ char *usn, /*! [in] Location URL. */ char *location, /*! [in] Service duration in sec. */ int duration, /*! [out] Output buffer filled with HTTP statement. */ char **packet, /*! [in] Address family of the HTTP request. */ int AddressFamily, /*! [in] PowerState as defined by UPnP Low Power. */ int PowerState, /*! [in] SleepPeriod as defined by UPnP Low Power. */ int SleepPeriod, /*! [in] RegistrationState as defined by UPnP Low Power. */ int RegistrationState) { int ret_code; const char *nts; membuffer buf; /* Notf == 0 means service shutdown, * Notf == 1 means service advertisement, * Notf == 2 means reply */ membuffer_init(&buf); buf.size_inc = (size_t)30; *packet = NULL; if (msg_type == MSGTYPE_REPLY) { if (PowerState > 0) { #ifdef UPNP_HAVE_OPTSSDP ret_code = http_MakeMessage(&buf, 1, 1, "R" "sdc" "D" "sc" "ssc" "ssc" "ssc" "S" "Xc" "ssc" "ssc" "sdc" "sdc" "sdcc", HTTP_OK, "CACHE-CONTROL: max-age=", duration, "EXT:", "LOCATION: ", location, "OPT: ", "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01", "01-NLS: ", gUpnpSdkNLSuuid, X_USER_AGENT, "ST: ", nt, "USN: ", usn, "Powerstate: ", PowerState, "SleepPeriod: ", SleepPeriod, "RegistrationState: ", RegistrationState); #else ret_code = http_MakeMessage(&buf, 1, 1, "R" "sdc" "D" "sc" "ssc" "S" "ssc" "ssc" "sdc" "sdc" "sdcc", HTTP_OK, "CACHE-CONTROL: max-age=", duration, "EXT:", "LOCATION: ", location, "ST: ", nt, "USN: ", usn, "Powerstate: ", PowerState, "SleepPeriod: ", SleepPeriod, "RegistrationState: ", RegistrationState); #endif /* UPNP_HAVE_OPTSSDP */ } else { #ifdef UPNP_HAVE_OPTSSDP ret_code = http_MakeMessage(&buf, 1, 1, "R" "sdc" "D" "sc" "ssc" "ssc" "ssc" "S" "Xc" "ssc" "sscc", HTTP_OK, "CACHE-CONTROL: max-age=", duration, "EXT:", "LOCATION: ", location, "OPT: ", "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01", "01-NLS: ", gUpnpSdkNLSuuid, X_USER_AGENT, "ST: ", nt, "USN: ", usn); #else ret_code = http_MakeMessage(&buf, 1, 1, "R" "sdc" "D" "sc" "ssc" "S" "ssc" "sscc", HTTP_OK, "CACHE-CONTROL: max-age=", duration, "EXT:", "LOCATION: ", location, "ST: ", nt, "USN: ", usn); #endif /* UPNP_HAVE_OPTSSDP */ } if (ret_code != 0) { return; } } else if (msg_type == MSGTYPE_ADVERTISEMENT || msg_type == MSGTYPE_SHUTDOWN) { const char *host = NULL; if (msg_type == MSGTYPE_ADVERTISEMENT) nts = "ssdp:alive"; else /* shutdown */ nts = "ssdp:byebye"; /* NOTE: The CACHE-CONTROL and LOCATION headers are not present in * a shutdown msg, but are present here for MS WinMe interop. */ switch (AddressFamily) { case AF_INET: host = SSDP_IP; break; default: if (isUrlV6UlaGua(location)) host = "[" SSDP_IPV6_SITELOCAL "]"; else host = "[" SSDP_IPV6_LINKLOCAL "]"; } if (PowerState > 0) { #ifdef UPNP_HAVE_OPTSSDP ret_code = http_MakeMessage(&buf, 1, 1, "Q" "sssdc" "sdc" "ssc" "ssc" "ssc" "ssc" "ssc" "S" "Xc" "ssc" "sdc" "sdc" "sdcc", HTTPMETHOD_NOTIFY, "*", (size_t) 1, "HOST: ", host, ":", SSDP_PORT, "CACHE-CONTROL: max-age=", duration, "LOCATION: ", location, "OPT: ", "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01", "01-NLS: ", gUpnpSdkNLSuuid, "NT: ", nt, "NTS: ", nts, X_USER_AGENT, "USN: ", usn, "Powerstate: ", PowerState, "SleepPeriod: ", SleepPeriod, "RegistrationState: ", RegistrationState); #else ret_code = http_MakeMessage(&buf, 1, 1, "Q" "sssdc" "sdc" "ssc" "ssc" "ssc" "S" "ssc" "sdc" "sdc" "sdcc", HTTPMETHOD_NOTIFY, "*", (size_t) 1, "HOST: ", host, ":", SSDP_PORT, "CACHE-CONTROL: max-age=", duration, "LOCATION: ", location, "NT: ", nt, "NTS: ", nts, "USN: ", usn, "Powerstate: ", PowerState, "SleepPeriod: ", SleepPeriod, "RegistrationState: ", RegistrationState); #endif /* UPNP_HAVE_OPTSSDP */ } else { #ifdef UPNP_HAVE_OPTSSDP ret_code = http_MakeMessage(&buf, 1, 1, "Q" "sssdc" "sdc" "ssc" "ssc" "ssc" "ssc" "ssc" "S" "Xc" "sscc", HTTPMETHOD_NOTIFY, "*", (size_t) 1, "HOST: ", host, ":", SSDP_PORT, "CACHE-CONTROL: max-age=", duration, "LOCATION: ", location, "OPT: ", "\"http://schemas.upnp.org/upnp/1/0/\"; ns=01", "01-NLS: ", gUpnpSdkNLSuuid, "NT: ", nt, "NTS: ", nts, X_USER_AGENT, "USN: ", usn); #else ret_code = http_MakeMessage(&buf, 1, 1, "Q" "sssdc" "sdc" "ssc" "ssc" "ssc" "S" "sscc", HTTPMETHOD_NOTIFY, "*", (size_t) 1, "HOST: ", host, ":", SSDP_PORT, "CACHE-CONTROL: max-age=", duration, "LOCATION: ", location, "NT: ", nt, "NTS: ", nts, "USN: ", usn); #endif /* UPNP_HAVE_OPTSSDP */ } if (ret_code) return; } else /* unknown msg */ assert(0); /* return msg */ *packet = membuffer_detach(&buf); membuffer_destroy(&buf); return; }
/*! * \brief This function retrives the name of the SOAP action. * * \return 0 if successful else returns appropriate error. */ static UPNP_INLINE int get_request_type( /*! [in] HTTP request. */ http_message_t *request, /*! [out] SOAP action name. */ memptr *action_name) { memptr value; memptr ns_value, dummy_quote; http_header_t *hdr; char save_char; char *s; membuffer soap_action_name; size_t n; /* find soapaction header */ if (request->method == SOAPMETHOD_POST) { if (!httpmsg_find_hdr(request, HDR_SOAPACTION, &value)) return SREQ_HDR_NOT_FOUND; } else { /* M-POST */ /* get NS value from MAN header */ hdr = httpmsg_find_hdr(request, HDR_MAN, &value); if (hdr == NULL) return SREQ_HDR_NOT_FOUND; if (matchstr(value.buf, value.length, "%q%i ; ns = %s", &dummy_quote, &ns_value) != 0) return SREQ_BAD_HDR_FORMAT; /* create soapaction name header */ membuffer_init(&soap_action_name); if (membuffer_assign(&soap_action_name, ns_value.buf, ns_value.length) == UPNP_E_OUTOF_MEMORY || membuffer_append_str(&soap_action_name, "-SOAPACTION") == UPNP_E_OUTOF_MEMORY) { membuffer_destroy(&soap_action_name); return UPNP_E_OUTOF_MEMORY; } hdr = httpmsg_find_hdr_str(request, soap_action_name.buf); membuffer_destroy(&soap_action_name); if (!hdr) return SREQ_HDR_NOT_FOUND; value.buf = hdr->value.buf; value.length = hdr->value.length; } /* determine type */ save_char = value.buf[value.length]; value.buf[value.length] = '\0'; s = strchr(value.buf, '#'); if (s == NULL) { value.buf[value.length] = save_char; return SREQ_BAD_HDR_FORMAT; } /* move to value */ s++; n = value.length - (size_t)(s - value.buf); if (matchstr(s, n, "%s", action_name) != PARSE_OK) { value.buf[value.length] = save_char; return SREQ_BAD_HDR_FORMAT; } /* action name or variable ? */ if (memptr_cmp(action_name, "QueryStateVariable") == 0) { /* query variable */ action_name->buf = NULL; action_name->length = 0; } /* restore */ value.buf[value.length] = save_char; return 0; }
/** * Internal helper function to do the work for * ib_kvstore_riak_set_bucket_property_int and * ib_kvstore_riak_set_bucket_property_str. */ static ib_status_t ib_kvstore_riak_set_bucket_property( ib_kvstore_t *kvstore, membuffer_t *request) { assert(kvstore); assert(request); assert(request->buffer); /* Constants for this function, alone. */ const char *props_path = "/props"; ib_kvstore_riak_server_t *riak; CURLcode curl_rc; struct curl_slist *header_list = NULL; size_t url_length; char *url; membuffer_t response; riak_headers_t headers; ib_status_t rc = IB_OK; riak_headers_init(kvstore, &headers); membuffer_init(kvstore, &response); riak = (ib_kvstore_riak_server_t *)kvstore->server; url_length = riak->bucket_url_len + strlen(props_path); url = kvmalloc(kvstore, url_length + 1); if (!url) { rc = IB_EALLOC; goto exit; } snprintf(url, url_length+1, "%s%s", riak->bucket_url, props_path); /* Set url. */ curl_rc = curl_easy_setopt(riak->curl, CURLOPT_URL, url); if (curl_rc) { rc = IB_EOTHER; goto exit; } /* Use PUT action. */ curl_rc = curl_easy_setopt(riak->curl, CURLOPT_UPLOAD, 1); if (curl_rc) { rc = IB_EOTHER; goto exit; } /* Set request data. */ curl_rc = curl_easy_setopt(riak->curl, CURLOPT_READDATA, request); if (curl_rc) { rc = IB_EOTHER; goto exit; } /* Set request data size. */ curl_rc = curl_easy_setopt(riak->curl, CURLOPT_INFILESIZE, request->size); if (curl_rc) { rc = IB_EOTHER; goto exit; } /* Define how to read the request. */ curl_rc = curl_easy_setopt( riak->curl, CURLOPT_READFUNCTION, membuffer_readfunction); if (curl_rc) { rc = IB_EOTHER; goto exit; } /* Define how to write the response. */ curl_rc = curl_easy_setopt( riak->curl, CURLOPT_WRITEFUNCTION, membuffer_writefunction); if (curl_rc) { rc = IB_EOTHER; goto exit; } /* Set the response buffer. */ curl_rc = curl_easy_setopt(riak->curl, CURLOPT_WRITEDATA, &response); if (curl_rc) { rc = IB_EOTHER; goto exit; } /* How are headers captures. */ curl_rc = curl_easy_setopt( riak->curl, CURLOPT_HEADERFUNCTION, &riak_header_capture); if (curl_rc) { rc = IB_EOTHER; goto exit; } /* Where are headers captures. */ curl_rc = curl_easy_setopt(riak->curl, CURLOPT_WRITEHEADER, &headers); if (curl_rc) { rc = IB_EOTHER; goto exit; } header_list = curl_slist_append(header_list, "Content-Type: application/json"); if (!header_list) { rc = IB_EOTHER; goto exit; } curl_rc = curl_easy_setopt(riak->curl, CURLOPT_HTTPHEADER, header_list); if (curl_rc) { rc = IB_EOTHER; goto exit; } /* Perform the transaction. */ curl_rc = curl_easy_perform(riak->curl); if (curl_rc) { rc = IB_EOTHER; goto exit; } exit: if (header_list) { curl_slist_free_all(header_list); } cleanup_membuffer(&response); cleanup_riak_headers(&headers); curl_easy_reset(riak->curl); kvfree(kvstore, url); return rc; }
void web_server_callback(http_parser_t *parser, INOUT http_message_t *req, SOCKINFO *info) { int ret; int timeout = 0; enum resp_type rtype = 0; membuffer headers; membuffer filename; struct xml_alias_t xmldoc; struct SendInstruction RespInstr; /*Initialize instruction header. */ RespInstr.IsVirtualFile = 0; RespInstr.IsChunkActive = 0; RespInstr.IsRangeActive = 0; RespInstr.IsTrailers = 0; memset(RespInstr.AcceptLanguageHeader, 0, sizeof(RespInstr.AcceptLanguageHeader)); /* init */ membuffer_init(&headers); membuffer_init(&filename); /*Process request should create the different kind of header depending on the */ /*the type of request. */ ret = process_request(req, &rtype, &headers, &filename, &xmldoc, &RespInstr); if (ret != HTTP_OK) { /* send error code */ http_SendStatusResponse(info, ret, req->major_version, req->minor_version); } else { /* send response */ switch (rtype) { case RESP_FILEDOC: http_SendMessage(info, &timeout, "Ibf", &RespInstr, headers.buf, headers.length, filename.buf); break; case RESP_XMLDOC: http_SendMessage(info, &timeout, "Ibb", &RespInstr, headers.buf, headers.length, xmldoc.doc.buf, xmldoc.doc.length); alias_release(&xmldoc); break; case RESP_WEBDOC: /*http_SendVirtualDirDoc(info, &timeout, "Ibf", &RespInstr, headers.buf, headers.length, filename.buf);*/ http_SendMessage(info, &timeout, "Ibf", &RespInstr, headers.buf, headers.length, filename.buf); break; case RESP_HEADERS: /* headers only */ http_SendMessage(info, &timeout, "b", headers.buf, headers.length); break; case RESP_POST: /* headers only */ ret = http_RecvPostMessage(parser, info, filename.buf, &RespInstr); /* Send response. */ http_MakeMessage(&headers, 1, 1, "RTLSXcCc", ret, "text/html", &RespInstr, X_USER_AGENT); http_SendMessage(info, &timeout, "b", headers.buf, headers.length); break; default: UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__, "webserver: Invalid response type received.\n"); assert(0); } } UpnpPrintf(UPNP_INFO, HTTP, __FILE__, __LINE__, "webserver: request processed...\n"); membuffer_destroy(&headers); membuffer_destroy(&filename); }
/** * Does a simple get of a Riak object. * * This will call riak_headers_init and membuffer_init on * @a riak_headers and @a response. * */ static ib_status_t riak_get( ib_kvstore_t *kvstore, ib_kvstore_riak_server_t *riak, const char *url, membuffer_t *response, riak_headers_t *riak_headers) { CURLcode curl_rc; struct curl_slist *header_list = NULL; /* Callback data for reading in the body. */ membuffer_init(kvstore, response); /* Callback data for storing the CURL headers. */ riak_headers_init(kvstore, riak_headers); /* Set url. */ curl_rc = curl_easy_setopt(riak->curl, CURLOPT_URL, url); if (curl_rc) { return IB_EOTHER; } /* Use HTTP GET. */ curl_rc = curl_easy_setopt(riak->curl, CURLOPT_HTTPGET, 1); if (curl_rc) { return IB_EOTHER; } curl_rc = curl_easy_setopt( riak->curl, CURLOPT_WRITEFUNCTION, membuffer_writefunction); if (curl_rc) { return IB_EOTHER; } curl_rc = curl_easy_setopt(riak->curl, CURLOPT_WRITEDATA, response); if (curl_rc) { return IB_EOTHER; } curl_rc = curl_easy_setopt( riak->curl, CURLOPT_HEADERFUNCTION, &riak_header_capture); if (curl_rc) { return IB_EOTHER; } curl_rc = curl_easy_setopt(riak->curl, CURLOPT_WRITEHEADER, riak_headers); if (curl_rc) { return IB_EOTHER; } header_list = build_custom_headers(kvstore, riak, NULL); if (header_list) { curl_rc = curl_easy_setopt( riak->curl, CURLOPT_HTTPHEADER, header_list); if (curl_rc) { return IB_EOTHER; } } /* Perform the transaction. */ curl_rc = curl_easy_perform(riak->curl); if (riak_headers->etag) { ib_kvstore_riak_set_etag(kvstore, riak_headers->etag); } if (riak_headers->x_riak_vclock) { ib_kvstore_riak_set_vclock(kvstore, riak_headers->x_riak_vclock); } /* Free the header list before checking curl_rc. */ if (header_list) { curl_slist_free_all(header_list); } if (curl_rc) { return IB_EOTHER; } return IB_OK; }
/**************************************************************************** * Function : send_error_response * * Parameters : * IN SOCKINFO *info : socket info * IN int error_code : error code * IN const char* err_msg : error message * IN http_message_t* hmsg : HTTP request * * Description : This function sends SOAP error response * * Return : void * * Note : ****************************************************************************/ static void send_error_response( IN SOCKINFO * info, IN int error_code, IN const char *err_msg, IN http_message_t * hmsg ) { int content_length; int timeout_secs = SOAP_TIMEOUT; int major, minor; const char *start_body = "<s:Envelope\n" "xmlns:s=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" "s:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\">\n" "<s:Body>\n" "<s:Fault>\n" "<faultcode>s:Client</faultcode>\n" "<faultstring>UPnPError</faultstring>\n" "<detail>\n" "<UPnPError xmlns=\"urn:schemas-upnp-org:control-1-0\">\n" "<errorCode>"; const char *mid_body = "</errorCode>\n" "<errorDescription>"; const char *end_body = "</errorDescription>\n" "</UPnPError>\n" "</detail>\n" "</s:Fault>\n" "</s:Body>\n" "</s:Envelope>\n"; char err_code_str[30]; membuffer headers; sprintf( err_code_str, "%d", error_code ); // calc body len content_length = strlen( start_body ) + strlen( err_code_str ) + strlen( mid_body ) + strlen( err_msg ) + strlen( end_body ); http_CalcResponseVersion( hmsg->major_version, hmsg->minor_version, &major, &minor ); // make headers membuffer_init( &headers ); if( http_MakeMessage( &headers, major, minor, "RNsDsSc" "sssss", 500, content_length, ContentTypeHeader, "EXT:\r\n", start_body, err_code_str, mid_body, err_msg, end_body ) != 0 ) { membuffer_destroy( &headers ); return; // out of mem } // send err msg http_SendMessage( info, &timeout_secs, "b", headers.buf, headers.length ); membuffer_destroy( &headers ); }
/**************************************************************************** * Function : get_request_type * * Parameters : * IN http_message_t* request : HTTP request * OUT memptr* action_name : SOAP action name * * Description : This function retrives the name of the SOAP action * * Return : int * 0 if successful else returns appropriate error. * Note : ****************************************************************************/ static XINLINE int get_request_type( IN http_message_t * request, OUT memptr * action_name ) { memptr value; memptr ns_value, dummy_quote; http_header_t *hdr; char save_char; char *s; membuffer soap_action_name; // find soapaction header // if( request->method == SOAPMETHOD_POST ) { if( httpmsg_find_hdr( request, HDR_SOAPACTION, &value ) == NULL ) { return SREQ_HDR_NOT_FOUND; } } else // M-POST { // get NS value from MAN header hdr = httpmsg_find_hdr( request, HDR_MAN, &value ); if( hdr == NULL ) { return SREQ_HDR_NOT_FOUND; } if( matchstr( value.buf, value.length, "%q%i ; ns = %s", &dummy_quote, &ns_value ) != 0 ) { return SREQ_BAD_HDR_FORMAT; } // create soapaction name header membuffer_init( &soap_action_name ); if( ( membuffer_assign( &soap_action_name, ns_value.buf, ns_value.length ) == UPNP_E_OUTOF_MEMORY ) || ( membuffer_append_str( &soap_action_name, "-SOAPACTION" ) == UPNP_E_OUTOF_MEMORY ) ) { membuffer_destroy( &soap_action_name ); return UPNP_E_OUTOF_MEMORY; } hdr = httpmsg_find_hdr_str( request, soap_action_name.buf ); membuffer_destroy( &soap_action_name ); if( hdr == NULL ) { return SREQ_HDR_NOT_FOUND; } value.buf = hdr->value.buf; value.length = hdr->value.length; } // determine type // save_char = value.buf[value.length]; value.buf[value.length] = '\0'; s = strchr( value.buf, '#' ); if( s == NULL ) { value.buf[value.length] = save_char; return SREQ_BAD_HDR_FORMAT; } s++; // move to value if( matchstr( s, value.length - ( s - value.buf ), "%s", action_name ) != PARSE_OK ) { value.buf[value.length] = save_char; return SREQ_BAD_HDR_FORMAT; } // action name or variable ? if( memptr_cmp( action_name, "QueryStateVariable" ) == 0 ) { // query variable action_name->buf = NULL; action_name->length = 0; } value.buf[value.length] = save_char; // restore return 0; }
static ib_status_t kvget( ib_kvstore_t *kvstore, const ib_kvstore_key_t *key, ib_kvstore_value_t ***values, size_t *values_length, ib_kvstore_cbdata_t *cbdata) { ib_status_t rc; ib_kvstore_riak_server_t *riak; char *url; membuffer_t response; riak_headers_t riak_headers; membuffer_init(kvstore, &response); riak_headers_init(kvstore, &riak_headers); riak = (ib_kvstore_riak_server_t *)kvstore->server; url = build_key_url(kvstore, riak, key); rc = riak_get(kvstore, riak, url, &response, &riak_headers); if (rc != IB_OK) { goto exit; } if (riak_headers.status == 200) { *values_length = 1; /* Build 1-element array. */ *values = kvmalloc(kvstore, sizeof(**values)); if (*values == NULL) { rc = IB_EALLOC; goto exit; } /* Allocate kvstore value. */ (*values)[0] = kvmalloc(kvstore, sizeof(*((*values)[0]))); if (*values[0] == NULL) { rc = IB_EALLOC; goto exit; } rc = http_to_kvstore_value( kvstore, riak, &response, &riak_headers, (*values)[0]); goto exit; } /* Multiple choices. */ else if (riak_headers.status == 300) { /* Current line. */ char *cur; *values_length = 0; /* Count the siblings returned in the buffer. */ for (size_t i = 0; i + 1 < response.read && response.buffer[i] != '\0'; ++i) { /* Every sibling etag is preceded by a '\n' */ if (response.buffer[i] == '\n' && isalnum(response.buffer[i+1])) { ++(*values_length); } } /* Build a *values_length element array. */ *values = kvmalloc(kvstore, sizeof(**values) * *values_length); if (*values == NULL) { rc = IB_EALLOC; goto exit; } /* For each sibling, fetch it to be merged. */ /* Skip the first line which is always "Siblings:\n". */ cur = index(response.buffer, '\n') + 1; for (size_t i = 0; i < *values_length; ++i) { /* URL containing ?vtag=<ETag> from response. */ char *vtag_url; const char *vtag = "?vtag="; char *eol = index(cur, '\n'); *eol = '\0'; membuffer_t tmp_buf; riak_headers_t tmp_headers; /* Init and Re-init. */ membuffer_init(kvstore, &tmp_buf); riak_headers_init(kvstore, &tmp_headers); vtag_url = kvmalloc( kvstore, strlen(url) + strlen(vtag) + strlen(cur) + 1); if (!vtag_url) { rc = IB_EALLOC; goto exit; } sprintf(vtag_url, "%s%s%s", url, vtag, cur); rc = riak_get(kvstore, riak, vtag_url, &tmp_buf, &tmp_headers); if (rc != IB_OK) { /* Nop - just skip this and decrement the results. */ --(*values_length); cleanup_membuffer(&tmp_buf); kvfree(kvstore, vtag_url); continue; } (*values)[i] = kvmalloc(kvstore, sizeof(*(*values)[i])); if ((*values)[i] == NULL) { /* On failure, free allocated keys. */ for(size_t j = 0; j < i; j++) { ib_kvstore_free_value(kvstore, (*values)[i]); } kvfree(kvstore, vtag_url); rc = IB_EALLOC; goto exit; } /* Convert the retrieved buffer data into a kvstore value. */ rc = http_to_kvstore_value( kvstore, riak, &tmp_buf, &tmp_headers, (*values)[i]); cleanup_membuffer(&tmp_buf); cleanup_riak_headers(&tmp_headers); kvfree(kvstore, vtag_url); cur = eol+1; } } else if (riak_headers.status == 404) { *values_length = 0; *values = NULL; goto exit; rc = IB_ENOENT; } /* Before cleanly existing, set the riak etag and vclock to that of * the representative request, not the individual etag ones. */ if (riak_headers.etag) { ib_kvstore_riak_set_etag(kvstore, riak_headers.etag); } if (riak_headers.x_riak_vclock) { ib_kvstore_riak_set_vclock(kvstore, riak_headers.x_riak_vclock); } exit: cleanup_membuffer(&response); cleanup_riak_headers(&riak_headers); curl_easy_reset(riak->curl); kvfree(kvstore, url); return rc; }