/*---------------------------------------------------------------------- | Listener_OnPropertyChanged +---------------------------------------------------------------------*/ static void Listener_OnPropertyChanged(ATX_PropertyListener* _self, ATX_CString name, ATX_PropertyType type, const ATX_PropertyValue* value) { Listener* self = ATX_SELF(Listener, ATX_PropertyListener); ATX_Debug("OnPropertyChanged[%s]: ", ATX_CSTR(self->name)); if (value) { PrintProperty(name, type, value); } else { ATX_Debug("name=%s [REMOVED]\n", name); } }
/*---------------------------------------------------------------------- | BtController::OnAckNotification +---------------------------------------------------------------------*/ void BtController::OnNackNotification(BLT_DecoderServer_Message::CommandId id, BLT_Result result) { ATX_Debug("BLT_Player::OnNackNotification (id=%d, result=%d:%s)\n", id, result, BLT_ResultText(result)); }
/*---------------------------------------------------------------------- | PrintProperty +---------------------------------------------------------------------*/ static void PrintProperty(ATX_CString name, ATX_PropertyType type, const ATX_PropertyValue* value) { ATX_Debug("name=%s ", name); switch (type) { case ATX_PROPERTY_TYPE_INTEGER: ATX_Debug("[INTEGER] %d (%x)\n", value->integer, value->integer); break; case ATX_PROPERTY_TYPE_FLOAT: ATX_Debug("[FLOAT] %f\n", value->fp); break; case ATX_PROPERTY_TYPE_BOOLEAN: ATX_Debug("[BOOL] %s\n", value->boolean == ATX_TRUE ? "TRUE" : "FALSE"); break; case ATX_PROPERTY_TYPE_STRING: ATX_Debug("[STRING] %s\n", value->string); break; case ATX_PROPERTY_TYPE_RAW_DATA: ATX_Debug("[DATA] %d bytes at %lx\n", value->raw_data.size, ATX_POINTER_TO_LONG(value->raw_data.data)); break; default: ATX_Debug("[UNKNOWN]\n"); break; } }
/*---------------------------------------------------------------------- | DumpProperties +---------------------------------------------------------------------*/ static void DumpProperties(ATX_Properties* properties) { ATX_Iterator* iterator; ATX_Property* property; ATX_Debug("[PROPERTIES] -------------------------------\n"); if (ATX_FAILED(ATX_Properties_GetIterator(properties, &iterator))) { return; } while (ATX_SUCCEEDED(ATX_Iterator_GetNext(iterator, (ATX_Any*)(void*)&property))) { PrintProperty(property->name, property->type, &property->value); } ATX_Debug("--------------------------------------------\n"); ATX_DESTROY_OBJECT(iterator); }
/*---------------------------------------------------------------------- | main +---------------------------------------------------------------------*/ int main(int argc, char** argv) { ATX_HttpClient* client; ATX_HttpRequest* request; ATX_HttpResponse* response; ATX_InputStream* response_body = NULL; ATX_Size response_body_size = 0; ATX_Result result; /* create a request */ result = ATX_HttpRequest_Create(ATX_HTTP_METHOD_GET, "http://zebulon.bok.net/tmp/redirect", &request); CHECK_RESULT(result, "ATX_HttpRequest_Create failed"); /* create a client */ result = ATX_HttpClient_Create(&client); CHECK_RESULT(result, "ATX_HttpClient_Create failed"); /* send the request and get a response */ result = ATX_HttpClient_SendRequest(client, request, &response); CHECK_RESULT(result, "ATX_HttpClient_SendRequest failed"); /* print the response */ ATX_Debug("StatusCode = %d\n", ATX_HttpResponse_GetStatusCode(response)); ATX_Debug("ResonPhrase = %s\n", ATX_String_GetChars(ATX_HttpResponse_GetReasonPhrase(response))); ATX_HttpMessage_GetBody((const ATX_HttpMessage*)response, NULL, &response_body_size); ATX_Debug("BodySize = %d\n", response_body_size); /* cleanup */ ATX_RELEASE_OBJECT(response_body); ATX_HttpResponse_Destroy(response); ATX_HttpRequest_Destroy(request); ATX_HttpClient_Destroy(client); return 0; }
/*---------------------------------------------------------------------- | ATX_HttpClient_SendRequest +---------------------------------------------------------------------*/ ATX_Result ATX_HttpClient_SendRequest(ATX_HttpClient* self, ATX_HttpRequest* request, ATX_HttpResponse** response) { ATX_Cardinal watchdog = ATX_HTTP_MAX_REDIRECTS; ATX_Boolean keep_going; ATX_Result result; do { keep_going = ATX_FALSE; result = ATX_HttpClient_SendRequestOnce(self, request, response); if (ATX_FAILED(result)) break; if (*response && self->options.follow_redirect && ((*response)->status_code == 301 || (*response)->status_code == 302 || (*response)->status_code == 303 || (*response)->status_code == 307)) { /* handle redirect */ const ATX_String* location = ATX_HttpMessage_GetHeader((ATX_HttpMessage*)*response, ATX_HTTP_HEADER_LOCATION); if (location) { /* replace the request url */ ATX_HttpUrl url; result = ATX_HttpUrl_Construct(&url, ATX_String_GetChars(location)); if (ATX_SUCCEEDED(result)) { ATX_HttpUrl_Destruct(&request->url); request->url = url; keep_going = ATX_TRUE; ATX_Debug("ATX_HttpClient::SendRequest - redirecting to %s\n", ATX_String_GetChars(location)); } } } } while (keep_going && watchdog--); return result; }
/*---------------------------------------------------------------------- | ATX_HttpMessage_Emit +---------------------------------------------------------------------*/ ATX_Result ATX_HttpMessage_Emit(const ATX_HttpMessage* message, ATX_OutputStream* stream) { ATX_ListItem* item = ATX_List_GetFirstItem(message->headers); /* output the headers */ while (item) { ATX_HttpHeader* header = ATX_ListItem_GetData(item); if (header && !ATX_String_IsEmpty(&header->name) && !ATX_String_IsEmpty(&header->value)) { ATX_OutputStream_WriteString(stream, ATX_CSTR(header->name)); ATX_OutputStream_Write(stream, ": ", 2, NULL); ATX_OutputStream_WriteLine(stream, ATX_CSTR(header->value)); ATX_Debug("ATX_HttpMessage::Emit - %s: %s\n", ATX_CSTR(header->name), ATX_CSTR(header->value)); } item = ATX_ListItem_GetNext(item); } return ATX_SUCCESS; }
/*---------------------------------------------------------------------- | ConnectClient +---------------------------------------------------------------------*/ static ATX_Result ConnectClient(ATX_ClientSocket* client, char* hostname, ATX_SocketPort port, ATX_ByteStream* stream) { ATX_Socket socket; ATX_Result result; ATX_Debug("connecting to %s on port %d\n", hostname, port); /* connect client */ result = ATX_ClientSocket_Connect(client, hostname, port, 10000); if (result != ATX_SUCCESS) { ATX_Debug("ERROR: connection failed (%d)\n", result); return result; } ATX_Debug("connected\n"); /* cast to ATX_Socket interface */ result = ATX_CAST_OBJECT(client, &socket, ATX_Socket); if (result != ATX_SUCCESS) { ATX_Debug("ERROR: client object does not implement the " "ATX_Socket interface\n"); return result; } /* get socket stream */ result = ATX_Socket_GetStream(&socket, stream); if (result != ATX_SUCCESS) { ATX_Debug("ERROR: cannot get socket stream\n"); return result; } /* check stream */ if (ATX_OBJECT_IS_NULL(stream)) { ATX_Debug("ERROR: stream is NULL\n"); return ATX_FAILURE; } return ATX_SUCCESS; }
/*---------------------------------------------------------------------- | ATX_HttpResponse_Parse +---------------------------------------------------------------------*/ static ATX_Result ATX_HttpResponse_Parse(ATX_HttpResponse* response, ATX_InputStream* stream) { char buffer[ATX_HTTP_MAX_LINE_SIZE+1]; char* line = buffer; char* find; ATX_Boolean header_pending = ATX_FALSE; ATX_String header_name = ATX_EMPTY_STRING; ATX_String header_value = ATX_EMPTY_STRING; ATX_Result result; /* get the first line from the stream */ result = ATX_InputStream_ReadLine(stream, line, sizeof(buffer), NULL); if (ATX_FAILED(result)) return result; /* get the protocol */ find = (char*)ATX_Http_FindChar(line, ' '); if (find == NULL) { return ATX_ERROR_INVALID_SYNTAX; } *find = '\0'; ATX_String_Assign(&response->base.protocol, line); /* get the status code */ line = (char*)ATX_Http_SkipWhitespace(find+1); find = (char*)ATX_Http_FindChar(line, ' '); if (find == NULL) { return ATX_ERROR_INVALID_SYNTAX; } *find = '\0'; if (ATX_StringLength(line) != 3) { return ATX_ERROR_INVALID_SYNTAX; } { int i; response->status_code = 0; for (i=0; i<3; i++) { if (line[i] < '0' || line[i] > '9') { return ATX_ERROR_INVALID_SYNTAX; } response->status_code *= 10; response->status_code += line[i]-'0'; } } /* the rest is the reason phrase */ line = (char*)ATX_Http_SkipWhitespace(find+1); ATX_String_Assign(&response->reason_phrase, line); /* parse headers until an empty line or end of stream */ do { /* read a line */ result = ATX_InputStream_ReadLine(stream, line, sizeof(buffer), NULL); if (ATX_FAILED(result)) break; /* stop if line is empty */ if (line[0] == '\0' || line[0] == '\r' || line[0] == '\n') { if (header_pending) { ATX_String_TrimWhitespace(&header_value); ATX_HttpMessage_SetHeader((ATX_HttpMessage*)response, ATX_CSTR(header_name), ATX_CSTR(header_value)); ATX_Debug("ATX_HttpResponse::Parse - %s: %s\n", ATX_CSTR(header_name), ATX_CSTR(header_value)); } break; } /* process the line */ if ((line[0] == ' ' || line[0] == '\t') && header_pending) { /* this is a line continuation */ ATX_String_Append(&header_value, line+1); } else { /* this is a new header */ const char* name; const char* value; /* add the pending header to the list */ if (header_pending) { ATX_String_TrimWhitespace(&header_value); ATX_HttpMessage_SetHeader((ATX_HttpMessage*)response, ATX_CSTR(header_name), ATX_CSTR(header_value)); ATX_Debug("ATX_HttpResponse::Parse - %s: %s\n", ATX_CSTR(header_name), ATX_CSTR(header_value)); } /* parse header name */ name = ATX_Http_SkipWhitespace(line); value = ATX_Http_FindChar(name, ':'); ATX_String_AssignN(&header_name, name, (ATX_Size)(value-name)); value = ATX_Http_SkipWhitespace(value+1); ATX_String_Assign(&header_value, value); /* don't add the header now, it could be continued */ header_pending = ATX_TRUE; } } while(ATX_SUCCEEDED(result)); /* keep a reference to the stream */ response->base.body = stream; ATX_REFERENCE_OBJECT(stream); /* cleanup */ ATX_String_Destruct(&header_name); ATX_String_Destruct(&header_value); return ATX_SUCCESS; }
/*---------------------------------------------------------------------- | ATX_HttpClient_SendRequestOnce +---------------------------------------------------------------------*/ static ATX_Result ATX_HttpClient_SendRequestOnce(ATX_HttpClient* self, ATX_HttpRequest* request, ATX_HttpResponse** response) { ATX_Socket* connection = NULL; ATX_SocketAddress address; ATX_InputStream* input_stream = NULL; ATX_OutputStream* output_stream = NULL; ATX_Result result; /* set default return value */ *response = NULL; /* resolve the host address */ ATX_Debug("ATX_HttpClient::SendRequest - resolving name [%s]...\n", ATX_CSTR(request->url.host)); result = ATX_IpAddress_ResolveName(&address.ip_address, ATX_CSTR(request->url.host), ATX_HTTP_RESOLVER_TIMEOUT); if (ATX_FAILED(result)) return result; address.port = request->url.port; ATX_Debug("ATX_HttpClient::SendRequest - name resolved\n"); /* setup some headers */ ATX_HttpMessage_SetHeader((ATX_HttpMessage*)request, ATX_HTTP_HEADER_CONNECTION, "close"); ATX_HttpMessage_SetHeader((ATX_HttpMessage*)request, ATX_HTTP_HEADER_HOST, ATX_CSTR(request->url.host)); ATX_HttpMessage_SetHeader((ATX_HttpMessage*)request, ATX_HTTP_HEADER_USER_AGENT, ATX_HTTP_HEADER_DEFAULT_AGENT); /* create a socket to connect to the server */ result = ATX_TcpClientSocket_Create(&connection); if (ATX_FAILED(result)) return result; /* connect to the server */ ATX_Debug("ATX_HttpClient::SendRequest - connecting on port %d...\n", request->url.port); result = ATX_Socket_Connect(connection, &address, ATX_HTTP_CONNECT_TIMEOUT); if (ATX_FAILED(result)) goto end; /* emit the request onto the connection */ result = ATX_Socket_GetOutputStream(connection, &output_stream); if (ATX_FAILED(result)) goto end; result = ATX_HttpRequest_Emit(request, output_stream); if (ATX_FAILED(result)) goto end; /* create a response from the connection's input stream */ result = ATX_Socket_GetInputStream(connection, &input_stream); if (ATX_FAILED(result)) goto end; result = ATX_HttpResponse_CreateFromStream(input_stream, response); if (ATX_FAILED(result)) goto end; end: if (ATX_FAILED(result)) { if (*response != NULL) { ATX_HttpResponse_Destroy(*response); } } ATX_RELEASE_OBJECT(input_stream); ATX_RELEASE_OBJECT(output_stream); ATX_DESTROY_OBJECT(connection); return result; }
/*---------------------------------------------------------------------- | BtController::OnAckNotification +---------------------------------------------------------------------*/ void BtController::OnAckNotification(BLT_DecoderServer_Message::CommandId id) { ATX_Debug("BLT_Player::OnAckNotification (id=%d)\n", id); }
/*---------------------------------------------------------------------- | main +---------------------------------------------------------------------*/ int main(int argc, char** argv) { ATX_Properties* properties; ATX_PropertyListener* listener0; ATX_PropertyListenerHandle listener0_handle = NULL; ATX_PropertyListener* listener1; ATX_PropertyListenerHandle listener1_handle = NULL; ATX_PropertyListener* listener2; ATX_PropertyListenerHandle listener2_handle = NULL; unsigned int i; unsigned int j; ATX_Result result; ATX_COMPILER_UNUSED(argc); ATX_COMPILER_UNUSED(argv); ATX_Debug("PropertiesTest -- Start\n"); Listener_Create("Listener 0", &listener0); Listener_Create("Listener 1", &listener1); Listener_Create("Listener 2", &listener2); result = ATX_Properties_Create(&properties); Properties[2].value.fp = 0.123456789f; j = 0; for (i=0; i<10000; i++) { DumpProperties(properties); if (rand()&0x4) { ATX_Debug("** setting property '%s' [%d]\n", Properties[j].name, j); result = ATX_Properties_SetProperty(properties, Properties[j].name, Properties[j].type, &Properties[j].value); ATX_Debug("(%d)\n", result); } else { ATX_Debug("&& unsetting property '%s' [%d]\n", Properties[j].name, j); result = ATX_Properties_UnsetProperty(properties, Properties[j].name); ATX_Debug("(%d)\n", result); } j++; if (j >= sizeof(Properties)/sizeof(Properties[0])) { j = 0; } if (rand()%7 == 0) { int l = rand()%3; ATX_PropertyListener* listener; ATX_PropertyListenerHandle* listener_handle; if (l == 0) { listener = listener0; listener_handle = &listener0_handle; } else if (l == 1) { listener = listener1; listener_handle = &listener1_handle; } else { listener = listener2; listener_handle = &listener2_handle; } if (*listener_handle) { result = ATX_Properties_RemoveListener(properties, *listener_handle); ATX_Debug("## removed listener %d [%d]\n", l, result); } result = ATX_Properties_AddListener(properties, Properties[j].name, listener, listener_handle); ATX_Debug("## added listener %d on %s [%d]\n", l, Properties[j].name, result); } ATX_Debug("++++++++++++++++++++++++++++++++++++++++++++\n"); } ATX_DESTROY_OBJECT(properties); ATX_DESTROY_OBJECT(listener0); ATX_DESTROY_OBJECT(listener1); ATX_DESTROY_OBJECT(listener2); ATX_Debug("PropertiesTest -- End\n"); return 0; }