/* * @brief Pumps the command cycle, sending the most recently gathered movement * to the server. */ void Cl_SendCmd(void) { mem_buf_t buf; byte data[128]; if (cls.state <= CL_CONNECTING) return; if (cls.state == CL_CONNECTED) { // send any reliable messages and / or don't timeout if (cls.net_chan.message.size || cls.real_time - cls.net_chan.last_sent > 1000) Netchan_Transmit(&cls.net_chan, NULL, 0); return; } // send a user info update if needed if (cvar_user_info_modified) { Net_WriteByte(&cls.net_chan.message, CL_CMD_USER_INFO); Net_WriteString(&cls.net_chan.message, Cvar_UserInfo()); cvar_user_info_modified = false; } // finalize the current command Cl_FinalizeCmd(); // and write it out Mem_InitBuffer(&buf, data, sizeof(data)); Net_WriteByte(&buf, CL_CMD_MOVE); // let the server know what the last frame we got was, so the next // message can be delta compressed if (!cl.frame.valid || (cls.demo_file && Fs_Tell(cls.demo_file) == 0)) Net_WriteLong(&buf, -1); // no compression else Net_WriteLong(&buf, cl.frame.frame_num); // send this and the previous two cmds in the message, so // if the last packet was dropped, it can be recovered static user_cmd_t null_cmd; cl_cmd_t *cmd = &cl.cmds[(cls.net_chan.outgoing_sequence - 2) & CMD_MASK]; Net_WriteDeltaUserCmd(&buf, &null_cmd, &cmd->cmd); user_cmd_t *old_cmd = &cmd->cmd; cmd = &cl.cmds[(cls.net_chan.outgoing_sequence - 1) & CMD_MASK]; Net_WriteDeltaUserCmd(&buf, old_cmd, &cmd->cmd); old_cmd = &cmd->cmd; cmd = &cl.cmds[(cls.net_chan.outgoing_sequence) & CMD_MASK]; Net_WriteDeltaUserCmd(&buf, old_cmd, &cmd->cmd); // deliver the message Netchan_Transmit(&cls.net_chan, buf.data, buf.size); cl.packet_counter++; // initialize the next command Cl_InitCmd(); }
static void SummonActor (int command, int command2, FCommandLine argv) { if (CheckCheatmode ()) return; if (argv.argc() > 1) { const PClass *type = PClass::FindClass (argv[1]); if (type == NULL) { Printf ("Unknown class '%s'\n", argv[1]); return; } Net_WriteByte (argv.argc() > 2 ? command2 : command); Net_WriteString (type->TypeName.GetChars()); if (argv.argc () > 2) { Net_WriteWord (atoi (argv[2])); // angle if (argv.argc () > 3) Net_WriteWord (atoi (argv[3])); // TID else Net_WriteWord (0); if (argv.argc () > 4) Net_WriteByte (atoi (argv[4])); // special else Net_WriteByte (0); for(int i = 5; i < 10; i++) { // args[5] if(i < argv.argc()) Net_WriteLong (atoi (argv[i])); else Net_WriteLong (0); } } } }
static void SummonActor (int command, int command2, FCommandLine argv) { if (CheckCheatmode ()) return; if (argv.argc() > 1) { PClassActor *type = PClass::FindActor(argv[1]); if (type == NULL) { Printf ("Unknown actor '%s'\n", argv[1]); return; } Net_WriteByte (argv.argc() > 2 ? command2 : command); Net_WriteString (type->TypeName.GetChars()); if (argv.argc () > 2) { Net_WriteWord (atoi (argv[2])); // angle Net_WriteWord ((argv.argc() > 3) ? atoi(argv[3]) : 0); // TID Net_WriteByte ((argv.argc() > 4) ? atoi(argv[4]) : 0); // special for (int i = 5; i < 10; i++) { // args[5] Net_WriteLong((i < argv.argc()) ? atoi(argv[i]) : 0); } } } }
/** * @brief Send data to the specified TCP stream. */ _Bool Net_SendStream(int32_t sock, const void *data, size_t len) { mem_buf_t buf; byte buffer[MAX_MSG_SIZE]; Mem_InitBuffer(&buf, buffer, sizeof(buffer)); // write the packet length Net_WriteLong(&buf, (int32_t) len); // and copy the payload Net_WriteData(&buf, data, len); ssize_t sent = 0; while ((size_t) sent < buf.size) { const ssize_t s = send(sock, (void *)(buf.data + sent), buf.size - sent, 0); if (s == -1) { if (Net_GetError() != EWOULDBLOCK) { Com_Warn("%s\n", Net_GetErrorString()); return false; } } sent += s; } return sent == (ssize_t) buf.size; }
void D_SendServerInfoChange (const FBaseCVar *cvar, UCVarValue value, ECVarType type) { size_t namelen; namelen = strlen (cvar->GetName ()); Net_WriteByte (DEM_SINFCHANGED); Net_WriteByte ((BYTE)(namelen | (type << 6))); Net_WriteBytes ((BYTE *)cvar->GetName (), (int)namelen); switch (type) { case CVAR_Bool: Net_WriteByte (value.Bool); break; case CVAR_Int: Net_WriteLong (value.Int); break; case CVAR_Float: Net_WriteFloat (value.Float); break; case CVAR_String: Net_WriteString (value.String); break; default: break; // Silence GCC } }
/** * @brief Writes the most recent movement command(s) using delta-compression if available. */ static void Cl_WriteMovementCommand(mem_buf_t *buf) { static cl_cmd_t null_cmd; Net_WriteByte(buf, CL_CMD_MOVE); if (!cl.frame.valid || (cls.demo_file && Fs_Tell(cls.demo_file) == 0)) { Net_WriteLong(buf, -1); } else { Net_WriteLong(buf, cl.frame.frame_num); } cl_cmd_t *from = &null_cmd, *to = &cl.cmds[(cls.net_chan.outgoing_sequence - 2) & CMD_MASK]; Net_WriteDeltaMoveCmd(buf, &from->cmd, &to->cmd); from = to; to = &cl.cmds[(cls.net_chan.outgoing_sequence - 1) & CMD_MASK]; Net_WriteDeltaMoveCmd(buf, &from->cmd, &to->cmd); from = to; to = &cl.cmds[(cls.net_chan.outgoing_sequence) & CMD_MASK]; Net_WriteDeltaMoveCmd(buf, &from->cmd, &to->cmd); }
/* * @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 */ void Sv_WriteClientFrame(sv_client_t *client, mem_buf_t *msg) { sv_frame_t *frame, *delta_frame; int32_t delta_frame_num; // this is the frame we are creating frame = &client->frames[sv.frame_num & PACKET_MASK]; if (client->last_frame < 0) { // client is asking for a retransmit delta_frame = NULL; delta_frame_num = -1; } else if (sv.frame_num - client->last_frame >= (PACKET_BACKUP - 3)) { // client hasn't gotten a good message through in a long time delta_frame = NULL; delta_frame_num = -1; } else { // we have a valid message to delta from delta_frame = &client->frames[client->last_frame & PACKET_MASK]; delta_frame_num = client->last_frame; } Net_WriteByte(msg, SV_CMD_FRAME); Net_WriteLong(msg, sv.frame_num); Net_WriteLong(msg, delta_frame_num); // what we are delta'ing from Net_WriteByte(msg, client->suppress_count); // rate dropped packets client->suppress_count = 0; // send over the area bits Net_WriteByte(msg, frame->area_bytes); Net_WriteData(msg, frame->area_bits, frame->area_bytes); // delta encode the player state Sv_WritePlayerState(delta_frame, frame, msg); // delta encode the entities Sv_WriteEntities(delta_frame, frame, msg); }
/* * @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); } }