/** * @brief Send the servers list to the specified client address. */ static void Ms_GetServers(struct sockaddr_in *from) { mem_buf_t buf; byte buffer[0xffff]; Mem_InitBuffer(&buf, buffer, sizeof(buffer)); const char *servers = "\xFF\xFF\xFF\xFF" "servers "; Mem_WriteBuffer(&buf, servers, strlen(servers)); uint32_t i = 0; GList *s = ms_servers; while (s) { const ms_server_t *server = (ms_server_t *) s->data; if (server->validated) { Mem_WriteBuffer(&buf, &server->addr.sin_addr, sizeof(server->addr.sin_addr)); Mem_WriteBuffer(&buf, &server->addr.sin_port, sizeof(server->addr.sin_port)); i++; } s = s->next; } if ((sendto(ms_sock, buf.data, buf.size, 0, (struct sockaddr *) from, sizeof(*from))) == -1) { Com_Warn("%s: %s\n", atos(from), strerror(errno)); } else { Com_Verbose("Sent %d servers to %s\n", i, atos(from)); } }
/* * @brief Sends an out-of-band datagram */ void Netchan_OutOfBand(int32_t sock, const net_addr_t *addr, const void *data, size_t len) { mem_buf_t send; byte send_buffer[MAX_MSG_SIZE]; // write the packet header Mem_InitBuffer(&send, send_buffer, sizeof(send_buffer)); Net_WriteLong(&send, -1); // -1 sequence means out of band Mem_WriteBuffer(&send, data, len); // send the datagram Net_SendDatagram(sock, addr, send.data, send.size); }
/* * @brief Tries to send an unreliable message to a connection, and handles the * transmission / retransmission of the reliable messages. * * A 0 size will still generate a packet and deal with the reliable messages. */ void Netchan_Transmit(net_chan_t *chan, byte *data, size_t len) { mem_buf_t send; byte send_buffer[MAX_MSG_SIZE]; // check for message overflow if (chan->message.overflowed) { chan->fatal_error = true; Com_Print("%s:Outgoing message overflow\n", Net_NetaddrToString(&chan->remote_address)); return; } const _Bool send_reliable = Netchan_NeedReliable(chan); if (!chan->reliable_size && chan->message.size) { memcpy(chan->reliable_buffer, chan->message_buffer, chan->message.size); chan->reliable_size = chan->message.size; chan->message.size = 0; chan->reliable_sequence ^= 1; } // write the packet header Mem_InitBuffer(&send, send_buffer, sizeof(send_buffer)); const uint32_t w1 = (chan->outgoing_sequence & ~(1 << 31)) | (send_reliable << 31); const uint32_t w2 = (chan->incoming_sequence & ~(1 << 31)) | (chan->incoming_reliable_sequence << 31); chan->outgoing_sequence++; chan->last_sent = quake2world.time; Net_WriteLong(&send, w1); Net_WriteLong(&send, w2); // send the qport if we are a client if (chan->source == NS_UDP_CLIENT) Net_WriteByte(&send, chan->qport); // copy the reliable message to the packet first if (send_reliable) { Mem_WriteBuffer(&send, chan->reliable_buffer, chan->reliable_size); chan->last_reliable_sequence = chan->outgoing_sequence; } // add the unreliable part if space is available if (send.max_size - send.size >= len) Mem_WriteBuffer(&send, data, len); else Com_Warn("Netchan_Transmit: dumped unreliable\n"); // send the datagram Net_SendDatagram(chan->source, &chan->remote_address, send.data, send.size); if (net_showpackets->value) { if (send_reliable) Com_Print("Send %u bytes: s=%i reliable=%i ack=%i rack=%i\n", (uint32_t) send.size, chan->outgoing_sequence - 1, chan->reliable_sequence, chan->incoming_sequence, chan->incoming_reliable_sequence); else Com_Print("Send %u bytes : s=%i ack=%i rack=%i\n", (uint32_t) send.size, chan->outgoing_sequence - 1, chan->incoming_sequence, chan->incoming_reliable_sequence); } }