ambrop7 14 жил өмнө
parent
commit
6dcf4d41ed
1 өөрчлөгдсөн 229 нэмэгдсэн , 274 устгасан
  1. 229 274
      server/server.c

+ 229 - 274
server/server.c

@@ -20,18 +20,6 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-/*
- NOTE:
- This program works with I/O inside the BPending job environment.
- A consequence of this is that in response to an input, we can't
- directly do any output, but instead have to schedule outputs.
- Because all the buffers used (e.g. client control buffers and peer flows)
- are based on flow components, it is impossible to directly write two or more
- packets to a buffer.
- To, for instance, send two packets to a buffer, we have to first schedule
- writing the second packet (using BPending), then send the first one.
-*/
-
 #include <inttypes.h>
 #include <stdlib.h>
 #include <string.h>
@@ -58,10 +46,10 @@
 #include <misc/loglevel.h>
 #include <misc/loggers_string.h>
 #include <predicate/BPredicate.h>
+#include <base/DebugObject.h>
 #include <base/BLog.h>
 #include <system/BSignal.h>
 #include <system/BTime.h>
-#include <base/DebugObject.h>
 #include <system/BAddr.h>
 #include <system/Listener.h>
 #include <security/BRandom.h>
@@ -165,10 +153,6 @@ LinkedList2 clients;
 // clients tree (by ID)
 BAVL clients_tree;
 
-// cleans everything up that can be cleaned in order to return
-// from the event loop and exit
-static void terminate (void);
-
 // prints help text to standard output
 static void print_help (const char *name);
 
@@ -184,22 +168,24 @@ static int process_arguments (void);
 // handler for program termination request
 static void signal_handler (void *unused);
 
-// listener socket handler, accepts new clients
+// listener handler, accepts new clients
 static void listener_handler (Listener *listener);
 
-// adds a client. The client structure must have the sock and addr members
-// already initialized.
-static void client_add (struct client_data *client);
+// frees resources used by a client
+static void client_dealloc (struct client_data *client);
+
+// initializes the I/O porition of the client
+static int client_init_io (struct client_data *client);
+
+// deallocates the I/O portion of the client. Must have no outgoing flows.
+static void client_dealloc_io (struct client_data *client);
 
 // removes a client
 static void client_remove (struct client_data *client);
 
-// job for notifying clients when a client is removed
+// job to finish removal after clients are informed
 static void client_dying_job (struct client_data *client);
 
-// frees resources used by a client
-static void client_dealloc (struct client_data *client);
-
 // passes a message to the logger, prepending about the client
 static void client_log (struct client_data *client, int level, const char *fmt, ...);
 
@@ -212,12 +198,6 @@ static void client_try_handshake (struct client_data *client);
 // event handler for driving client SSL handshake
 static void client_handshake_read_handler (struct client_data *client, PRInt16 event);
 
-// initializes the I/O porition of the client
-static int client_init_io (struct client_data *client);
-
-// deallocates the I/O portion of the client. Must have no outgoing flows.
-static void client_dealloc_io (struct client_data *client);
-
 // handler for client I/O errors. Removes the client.
 static void client_error_handler (struct client_data *client, int component, int code);
 
@@ -577,14 +557,6 @@ fail0:
     return 1;
 }
 
-void terminate (void)
-{
-    BLog(BLOG_NOTICE, "tearing down");
-    
-    // exit event loop
-    BReactor_Quit(&ss, 0);
-}
-
 void print_help (const char *name)
 {
     printf(
@@ -800,8 +772,8 @@ void signal_handler (void *unused)
 {
     BLog(BLOG_NOTICE, "termination requested");
     
-    terminate();
-    return;
+    // exit event loop
+    BReactor_Quit(&ss, 0);
 }
 
 void listener_handler (Listener *listener)
@@ -818,24 +790,16 @@ void listener_handler (Listener *listener)
         goto fail0;
     }
     
-    // accept it
+    // accept connection
     if (!Listener_Accept(listener, &client->sock, &client->addr)) {
         BLog(BLOG_NOTICE, "Listener_Accept failed");
         goto fail1;
     }
     
-    client_add(client);
-    return;
-    
-fail1:
-    free(client);
-fail0:
-    ;
-}
-
-void client_add (struct client_data *client)
-{
-    ASSERT(clients_num < MAX_CLIENTS)
+    // limit socket send buffer, else our scheduling is pointless
+    if (BSocket_SetSendBuffer(&client->sock, CLIENT_SOCKET_SEND_BUFFER) < 0) {
+        BLog(BLOG_WARNING, "BSocket_SetSendBuffer failed");
+    }
     
     // assign ID
     client->id = new_client_id();
@@ -846,8 +810,6 @@ void client_add (struct client_data *client)
     // now client_log() works
     
     if (options.ssl) {
-        // initialize SSL
-        
         // create BSocket NSPR file descriptor
         BSocketPRFileDesc_Create(&client->bottom_prfd, &client->sock);
         
@@ -855,23 +817,23 @@ void client_add (struct client_data *client)
         if (!(client->ssl_prfd = SSL_ImportFD(model_prfd, &client->bottom_prfd))) {
             client_log(client, BLOG_ERROR, "SSL_ImportFD failed");
             ASSERT_FORCE(PR_Close(&client->bottom_prfd) == PR_SUCCESS)
-            goto fail0;
+            goto fail2;
         }
         
         // set server mode
         if (SSL_ResetHandshake(client->ssl_prfd, PR_TRUE) != SECSuccess) {
             client_log(client, BLOG_ERROR, "SSL_ResetHandshake failed");
-            goto fail1;
+            goto fail3;
         }
         
         // set require client certificate
         if (SSL_OptionSet(client->ssl_prfd, SSL_REQUEST_CERTIFICATE, PR_TRUE) != SECSuccess) {
             client_log(client, BLOG_ERROR, "SSL_OptionSet(SSL_REQUEST_CERTIFICATE) failed");
-            goto fail1;
+            goto fail3;
         }
         if (SSL_OptionSet(client->ssl_prfd, SSL_REQUIRE_CERTIFICATE, PR_TRUE) != SECSuccess) {
             client_log(client, BLOG_ERROR, "SSL_OptionSet(SSL_REQUIRE_CERTIFICATE) failed");
-            goto fail1;
+            goto fail3;
         }
         
         // initialize BPRFileDesc on SSL file descriptor
@@ -879,7 +841,7 @@ void client_add (struct client_data *client)
     } else {
         // initialize I/O
         if (!client_init_io(client)) {
-            goto fail0;
+            goto fail2;
         }
     }
     
@@ -921,71 +883,15 @@ void client_add (struct client_data *client)
         return;
     }
     
-    // cleanup on errors
-fail1:
     if (options.ssl) {
+fail3:
         ASSERT_FORCE(PR_Close(client->ssl_prfd) == PR_SUCCESS)
     }
-fail0:
+fail2:
     BSocket_Free(&client->sock);
+fail1:
     free(client);
-}
-
-void client_remove (struct client_data *client)
-{
-    ASSERT(!client->dying)
-    
-    client_log(client, BLOG_NOTICE, "removing");
-    
-    // set dying to prevent sending this client anything
-    client->dying = 1;
-    
-    // free I/O (including incoming flows)
-    if (client->initstatus >= INITSTATUS_WAITHELLO) {
-        client_dealloc_io(client);
-    }
-    
-    // remove outgoing knows
-    LinkedList2Node *node;
-    while (node = LinkedList2_GetFirst(&client->know_out_list)) {
-        struct peer_know *k = UPPER_OBJECT(node, struct peer_know, from_node);
-        remove_know(k);
-    }
-    
-    // remove outgoing flows
-    while (node = LinkedList2_GetFirst(&client->peer_out_flows_list)) {
-        struct peer_flow *flow = UPPER_OBJECT(node, struct peer_flow, src_list_node);
-        ASSERT(flow->src_client == client)
-        ASSERT(flow->dest_client->initstatus == INITSTATUS_COMPLETE && !flow->dest_client->dying)
-        
-        if (PacketPassFairQueueFlow_IsBusy(&flow->qflow)) {
-            client_log(client, BLOG_DEBUG, "removing flow later");
-            peer_flow_disconnect(flow);
-            PacketPassFairQueueFlow_SetBusyHandler(&flow->qflow, (PacketPassFairQueue_handler_busy)peer_flow_handler_canremove, flow);
-        } else {
-            client_log(client, BLOG_DEBUG, "removing flow now");
-            peer_flow_dealloc(flow);
-        }
-    }
-    
-    // schedule job to finish removal after clients are informed
-    BPending_Set(&client->dying_job);
-    
-    // inform other clients that 'client' is no more
-    LinkedList2Iterator it;
-    LinkedList2Iterator_InitForward(&it, &client->know_in_list);
-    while (node = LinkedList2Iterator_Next(&it)) {
-        struct peer_know *k = UPPER_OBJECT(node, struct peer_know, to_node);
-        uninform_know(k);
-    }
-}
-
-void client_dying_job (struct client_data *client)
-{
-    ASSERT(client->dying)
-    ASSERT(LinkedList2_IsEmpty(&client->know_in_list))
-    
-    client_dealloc(client);
+fail0:
     return;
 }
 
@@ -1013,10 +919,7 @@ void client_dealloc (struct client_data *client)
     
     // free SSL
     if (options.ssl) {
-        // free BPRFileDesc
         BPRFileDesc_Free(&client->ssl_bprfd);
-        
-        // free SSL PRFD
         ASSERT_FORCE(PR_Close(client->ssl_prfd) == PR_SUCCESS)
     }
     
@@ -1032,132 +935,6 @@ void client_dealloc (struct client_data *client)
     free(client);
 }
 
-void client_log (struct client_data *client, int level, const char *fmt, ...)
-{
-    va_list vl;
-    va_start(vl, fmt);
-    char addr[BADDR_MAX_PRINT_LEN];
-    BAddr_Print(&client->addr, addr);
-    BLog_Append("client %d (%s)", (int)client->id, addr);
-    if (client->common_name) {
-        BLog_Append(" (%s)", client->common_name);
-    }
-    BLog_Append(": ");
-    BLog_LogToChannelVarArg(BLOG_CURRENT_CHANNEL, level, fmt, vl);
-    va_end(vl);
-}
-
-void client_disconnect_timer_handler (struct client_data *client)
-{
-    ASSERT(!client->dying)
-    
-    client_log(client, BLOG_NOTICE, "timed out");
-    
-    client_remove(client);
-    return;
-}
-
-void client_try_handshake (struct client_data *client)
-{
-    ASSERT(client->initstatus == INITSTATUS_HANDSHAKE)
-    ASSERT(!client->dying)
-    
-    // attempt handshake
-    if (SSL_ForceHandshake(client->ssl_prfd) != SECSuccess) {
-        PRErrorCode error = PR_GetError();
-        if (error == PR_WOULD_BLOCK_ERROR) {
-            // try again on read event
-            BPRFileDesc_EnableEvent(&client->ssl_bprfd, PR_POLL_READ);
-            return;
-        }
-        client_log(client, BLOG_NOTICE, "SSL_ForceHandshake failed (%d)", (int)error);
-        goto fail0;
-    }
-    
-    // remove read handler
-    BPRFileDesc_RemoveEventHandler(&client->ssl_bprfd, PR_POLL_READ);
-    
-    // get client certificate
-    CERTCertificate *cert = SSL_PeerCertificate(client->ssl_prfd);
-    if (!cert) {
-        client_log(client, BLOG_ERROR, "SSL_PeerCertificate failed");
-        goto fail0;
-    }
-    
-    // remember common name
-    if (!(client->common_name = CERT_GetCommonName(&cert->subject))) {
-        client_log(client, BLOG_NOTICE, "CERT_GetCommonName failed");
-        goto fail1;
-    }
-    
-    // store certificate
-    SECItem der = cert->derCert;
-    if (der.len > sizeof(client->cert)) {
-        client_log(client, BLOG_NOTICE, "client certificate too big");
-        goto fail1;
-    }
-    memcpy(client->cert, der.data, der.len);
-    client->cert_len = der.len;
-    
-    PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
-    if (!arena) {
-        client_log(client, BLOG_ERROR, "PORT_NewArena failed");
-        goto fail1;
-    }
-    
-    // encode certificate
-    memset(&der, 0, sizeof(der));
-    if (!SEC_ASN1EncodeItem(arena, &der, cert, SEC_ASN1_GET(CERT_CertificateTemplate))) {
-        client_log(client, BLOG_ERROR, "SEC_ASN1EncodeItem failed");
-        goto fail2;
-    }
-    
-    // store re-encoded certificate (for compatibility with old clients)
-    if (der.len > sizeof(client->cert_old)) {
-        client_log(client, BLOG_NOTICE, "client certificate too big");
-        goto fail2;
-    }
-    memcpy(client->cert_old, der.data, der.len);
-    client->cert_old_len = der.len;
-    
-    // init I/O chains
-    if (!client_init_io(client)) {
-        goto fail2;
-    }
-    
-    PORT_FreeArena(arena, PR_FALSE);
-    CERT_DestroyCertificate(cert);
-    
-    // set client state
-    client->initstatus = INITSTATUS_WAITHELLO;
-    
-    client_log(client, BLOG_INFO, "handshake complete");
-    
-    return;
-    
-    // handle errors
-fail2:
-    PORT_FreeArena(arena, PR_FALSE);
-fail1:
-    CERT_DestroyCertificate(cert);
-fail0:
-    client_remove(client);
-}
-
-void client_handshake_read_handler (struct client_data *client, PRInt16 event)
-{
-    ASSERT(client->initstatus == INITSTATUS_HANDSHAKE)
-    ASSERT(!client->dying)
-    ASSERT(event == PR_POLL_READ)
-    
-    // restart no data timer
-    BReactor_SetTimer(&ss, &client->disconnect_timer);
-    
-    // continue handshake
-    client_try_handshake(client);
-    return;
-}
-
 int client_init_io (struct client_data *client)
 {
     // initialize error domain
@@ -1179,8 +956,7 @@ int client_init_io (struct client_data *client)
     PacketPassInterface_Init(&client->input_interface, SC_MAX_ENC, (PacketPassInterface_handler_send)client_input_handler_send, client, BReactor_PendingGroup(&ss));
     
     // init decoder
-    if (!PacketProtoDecoder_Init(
-        &client->input_decoder, FlowErrorReporter_Create(&client->domain, COMPONENT_DECODER),
+    if (!PacketProtoDecoder_Init(&client->input_decoder, FlowErrorReporter_Create(&client->domain, COMPONENT_DECODER),
         source_interface, &client->input_interface, BReactor_PendingGroup(&ss)
     )) {
         client_log(client, BLOG_ERROR, "PacketProtoDecoder_Init failed");
@@ -1300,6 +1076,191 @@ void client_dealloc_io (struct client_data *client)
     }
 }
 
+void client_remove (struct client_data *client)
+{
+    ASSERT(!client->dying)
+    
+    client_log(client, BLOG_INFO, "removing");
+    
+    // set dying to prevent sending this client anything
+    client->dying = 1;
+    
+    // free I/O now, removing incoming flows
+    if (client->initstatus >= INITSTATUS_WAITHELLO) {
+        client_dealloc_io(client);
+    }
+    
+    // remove outgoing knows
+    LinkedList2Node *node;
+    while (node = LinkedList2_GetFirst(&client->know_out_list)) {
+        struct peer_know *k = UPPER_OBJECT(node, struct peer_know, from_node);
+        remove_know(k);
+    }
+    
+    // remove outgoing flows
+    while (node = LinkedList2_GetFirst(&client->peer_out_flows_list)) {
+        struct peer_flow *flow = UPPER_OBJECT(node, struct peer_flow, src_list_node);
+        ASSERT(flow->src_client == client)
+        ASSERT(flow->dest_client->initstatus == INITSTATUS_COMPLETE)
+        ASSERT(!flow->dest_client->dying)
+        
+        if (PacketPassFairQueueFlow_IsBusy(&flow->qflow)) {
+            client_log(client, BLOG_DEBUG, "removing flow to %d later", (int)flow->dest_client->id);
+            peer_flow_disconnect(flow);
+            PacketPassFairQueueFlow_SetBusyHandler(&flow->qflow, (PacketPassFairQueue_handler_busy)peer_flow_handler_canremove, flow);
+        } else {
+            client_log(client, BLOG_DEBUG, "removing flow to %d now", (int)flow->dest_client->id);
+            peer_flow_dealloc(flow);
+        }
+    }
+    
+    // schedule job to finish removal after clients are informed
+    BPending_Set(&client->dying_job);
+    
+    // inform other clients that 'client' is no more
+    LinkedList2Iterator it;
+    LinkedList2Iterator_InitForward(&it, &client->know_in_list);
+    while (node = LinkedList2Iterator_Next(&it)) {
+        struct peer_know *k = UPPER_OBJECT(node, struct peer_know, to_node);
+        uninform_know(k);
+    }
+}
+
+void client_dying_job (struct client_data *client)
+{
+    ASSERT(client->dying)
+    ASSERT(LinkedList2_IsEmpty(&client->know_in_list))
+    
+    client_dealloc(client);
+    return;
+}
+
+void client_log (struct client_data *client, int level, const char *fmt, ...)
+{
+    va_list vl;
+    va_start(vl, fmt);
+    char addr[BADDR_MAX_PRINT_LEN];
+    BAddr_Print(&client->addr, addr);
+    BLog_Append("client %d (%s)", (int)client->id, addr);
+    if (client->common_name) {
+        BLog_Append(" (%s)", client->common_name);
+    }
+    BLog_Append(": ");
+    BLog_LogToChannelVarArg(BLOG_CURRENT_CHANNEL, level, fmt, vl);
+    va_end(vl);
+}
+
+void client_disconnect_timer_handler (struct client_data *client)
+{
+    ASSERT(!client->dying)
+    
+    client_log(client, BLOG_INFO, "timed out");
+    
+    client_remove(client);
+    return;
+}
+
+void client_try_handshake (struct client_data *client)
+{
+    ASSERT(client->initstatus == INITSTATUS_HANDSHAKE)
+    ASSERT(!client->dying)
+    
+    // attempt handshake
+    if (SSL_ForceHandshake(client->ssl_prfd) != SECSuccess) {
+        PRErrorCode error = PR_GetError();
+        if (error == PR_WOULD_BLOCK_ERROR) {
+            // try again on read event
+            BPRFileDesc_EnableEvent(&client->ssl_bprfd, PR_POLL_READ);
+            return;
+        }
+        client_log(client, BLOG_NOTICE, "SSL_ForceHandshake failed (%d)", (int)error);
+        goto fail0;
+    }
+    
+    // remove read handler
+    BPRFileDesc_RemoveEventHandler(&client->ssl_bprfd, PR_POLL_READ);
+    
+    // get client certificate
+    CERTCertificate *cert = SSL_PeerCertificate(client->ssl_prfd);
+    if (!cert) {
+        client_log(client, BLOG_ERROR, "SSL_PeerCertificate failed");
+        goto fail0;
+    }
+    
+    // remember common name
+    if (!(client->common_name = CERT_GetCommonName(&cert->subject))) {
+        client_log(client, BLOG_NOTICE, "CERT_GetCommonName failed");
+        goto fail1;
+    }
+    
+    // store certificate
+    SECItem der = cert->derCert;
+    if (der.len > sizeof(client->cert)) {
+        client_log(client, BLOG_NOTICE, "client certificate too big");
+        goto fail1;
+    }
+    memcpy(client->cert, der.data, der.len);
+    client->cert_len = der.len;
+    
+    PRArenaPool *arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
+    if (!arena) {
+        client_log(client, BLOG_ERROR, "PORT_NewArena failed");
+        goto fail1;
+    }
+    
+    // encode certificate
+    memset(&der, 0, sizeof(der));
+    if (!SEC_ASN1EncodeItem(arena, &der, cert, SEC_ASN1_GET(CERT_CertificateTemplate))) {
+        client_log(client, BLOG_ERROR, "SEC_ASN1EncodeItem failed");
+        goto fail2;
+    }
+    
+    // store re-encoded certificate (for compatibility with old clients)
+    if (der.len > sizeof(client->cert_old)) {
+        client_log(client, BLOG_NOTICE, "client certificate too big");
+        goto fail2;
+    }
+    memcpy(client->cert_old, der.data, der.len);
+    client->cert_old_len = der.len;
+    
+    // init I/O chains
+    if (!client_init_io(client)) {
+        goto fail2;
+    }
+    
+    PORT_FreeArena(arena, PR_FALSE);
+    CERT_DestroyCertificate(cert);
+    
+    // set client state
+    client->initstatus = INITSTATUS_WAITHELLO;
+    
+    client_log(client, BLOG_INFO, "handshake complete");
+    
+    return;
+    
+    // handle errors
+fail2:
+    PORT_FreeArena(arena, PR_FALSE);
+fail1:
+    CERT_DestroyCertificate(cert);
+fail0:
+    client_remove(client);
+}
+
+void client_handshake_read_handler (struct client_data *client, PRInt16 event)
+{
+    ASSERT(client->initstatus == INITSTATUS_HANDSHAKE)
+    ASSERT(!client->dying)
+    ASSERT(event == PR_POLL_READ)
+    
+    // restart no data timer
+    BReactor_SetTimer(&ss, &client->disconnect_timer);
+    
+    // continue handshake
+    client_try_handshake(client);
+    return;
+}
+
 void client_error_handler (struct client_data *client, int component, int code)
 {
     ASSERT(INITSTATUS_HASLINK(client->initstatus))
@@ -1323,7 +1284,7 @@ int client_start_control_packet (struct client_data *client, void **data, int le
     // obtain location for writing the packet
     if (!BufferWriter_StartPacket(client->output_control_input, &client->output_control_packet)) {
         // out of buffer, kill client
-        client_log(client, BLOG_NOTICE, "out of control buffer, removing");
+        client_log(client, BLOG_INFO, "out of control buffer, removing");
         client_remove(client);
         return -1;
     }
@@ -1410,26 +1371,25 @@ void client_input_handler_send (struct client_data *client, uint8_t *data, int d
     ASSERT(INITSTATUS_HASLINK(client->initstatus))
     ASSERT(!client->dying)
     
+    // accept packet
+    PacketPassInterface_Done(&client->input_interface);
+    
+    // restart disconnect timer
+    BReactor_SetTimer(&ss, &client->disconnect_timer);
+    
+    // parse header
     if (data_len < sizeof(struct sc_header)) {
         client_log(client, BLOG_NOTICE, "packet too short");
         client_remove(client);
         return;
     }
-    
     struct sc_header *header = (struct sc_header *)data;
+    data += sizeof(*header);
+    data_len -= sizeof(*header);
     uint8_t type = ltoh8(header->type);
     
-    uint8_t *sc_data = data + sizeof(struct sc_header);
-    int sc_data_len = data_len - sizeof(struct sc_header);
-    
-    ASSERT(sc_data_len >= 0)
-    ASSERT(sc_data_len <= SC_MAX_PAYLOAD)
-    
-    // restart no data timer
-    BReactor_SetTimer(&ss, &client->disconnect_timer);
-    
-    // accept packet
-    PacketPassInterface_Done(&client->input_interface);
+    ASSERT(data_len >= 0)
+    ASSERT(data_len <= SC_MAX_PAYLOAD)
     
     // perform action based on packet type
     switch (type) {
@@ -1437,13 +1397,13 @@ void client_input_handler_send (struct client_data *client, uint8_t *data, int d
             client_log(client, BLOG_DEBUG, "received keep-alive");
             return;
         case SCID_CLIENTHELLO:
-            process_packet_hello(client, sc_data, sc_data_len);
+            process_packet_hello(client, data, data_len);
             return;
         case SCID_OUTMSG:
-            process_packet_outmsg(client, sc_data, sc_data_len);
+            process_packet_outmsg(client, data, data_len);
             return;
         default:
-            client_log(client, BLOG_NOTICE, "unknown packet type %d, removing", (int)header->type);
+            client_log(client, BLOG_NOTICE, "unknown packet type %d, removing", (int)type);
             client_remove(client);
             return;
     }
@@ -1474,11 +1434,6 @@ void process_packet_hello (struct client_data *client, uint8_t *data, int data_l
     
     client_log(client, BLOG_INFO, "received hello");
     
-    // limit socket send buffer, else our scheduling is pointless
-    if (BSocket_SetSendBuffer(&client->sock, CLIENT_SOCKET_SEND_BUFFER) < 0) {
-        BLog(BLOG_WARNING, "BSocket_SetSendBuffer failed");
-    }
-    
     // set client state to complete
     client->initstatus = INITSTATUS_COMPLETE;
     
@@ -1523,7 +1478,7 @@ void process_packet_hello (struct client_data *client, uint8_t *data, int data_l
     }
     pack->flags = htol16(0);
     pack->id = htol16(client->id);
-    pack->clientAddr = (client->addr.type == BADDR_TYPE_IPV4 ? client->addr.ipv4.ip : htol32(0));
+    pack->clientAddr = (client->addr.type == BADDR_TYPE_IPV4 ? client->addr.ipv4.ip : hton32(0));
     client_end_control_packet(client, SCID_SERVERHELLO);
     
     return;