source: network-game/common/MessageProcessor.cpp@ f9cb9fb

Last change on this file since f9cb9fb was f9cb9fb, checked in by dportnoy <dmp1488@…>, 11 years ago

The ackedMessages list in MessageProcessor now stores ack records based on sender address and message id so that messages with the same id, but from different senders are distinguishable

  • Property mode set to 100644
File size: 4.8 KB
RevLine 
[1a3c42d]1#include "MessageProcessor.h"
2
[5a64bea]3#include <iostream>
[d05086b]4#include <fstream>
[5a64bea]5
[198cf2d]6#include "Common.h"
7
[5a64bea]8MessageProcessor::MessageProcessor() {
9 lastUsedId = 0;
10}
11
12MessageProcessor::~MessageProcessor() {
13}
14
[d05086b]15int MessageProcessor::sendMessage(NETWORK_MSG *msg, int sock, struct sockaddr_in *dest, ofstream* outputLog) {
[46d6469]16 cout << "Sending message of type " << msg->type << endl;
17
[9b5d30b]18 msg->id = ++lastUsedId;
[5a64bea]19 MessageContainer message(*msg, *dest);
[d05086b]20
21 if (outputLog)
22 (*outputLog) << "Sending message (id " << msg->id << ") of type " << MessageContainer::getMsgTypeString(msg->type) << endl;
[5a64bea]23
[46d6469]24 sentMessages[msg->id][dest->sin_addr.s_addr] = message;
[bd2502a]25
[5a64bea]26 int ret = sendto(sock, (char*)msg, sizeof(NETWORK_MSG), 0, (struct sockaddr *)dest, sizeof(struct sockaddr_in));
27
28 return ret;
[1a3c42d]29}
30
[d05086b]31int MessageProcessor::receiveMessage(NETWORK_MSG *msg, int sock, struct sockaddr_in *source, ofstream* outputLog) {
[5a64bea]32 socklen_t socklen = sizeof(struct sockaddr_in);
33
34 // assume we don't care about the value of socklen
35 int ret = recvfrom(sock, (char*)msg, sizeof(NETWORK_MSG), 0, (struct sockaddr *)source, &socklen);
36
[6b641af]37 if (ret == -1)
38 return ret;
39
[5a64bea]40 // add id to the NETWORK_MSG struct
41 if (msg->type == MSG_TYPE_ACK) {
[46d6469]42 if (!sentMessages[msg->id][source->sin_addr.s_addr].getAcked()) {
43 sentMessages[msg->id][source->sin_addr.s_addr].setAcked(true);
44 sentMessages[msg->id][source->sin_addr.s_addr].setTimeAcked(getCurrentMillis());
[d05086b]45 if (outputLog)
46 (*outputLog) << "Received ack for message id " << msg->id << endl;
[6b641af]47 }
[198cf2d]48
49 return -1; // don't do any further processing
[5a64bea]50 }else {
[bace57b]51 bool isDuplicate = false;
[f9cb9fb]52 map<unsigned int, unsigned long long>& ackedPlayerMessages = ackedMessages[source->sin_addr.s_addr];
[bace57b]53
[f9cb9fb]54 if (ackedPlayerMessages.find(msg->id) != ackedPlayerMessages.end()) {
[bace57b]55 isDuplicate = true;
[934ab53]56 cout << "Got duplicate of type " << msg->type << endl;
[f9cb9fb]57 if (outputLog)
58 (*outputLog) << "Received duplicate (id " << msg->id << ") of type " << MessageContainer::getMsgTypeString(msg->type) << endl;
[d05086b]59 }else {
[934ab53]60 cout << "Got message of type " << msg->type << endl;
[d05086b]61 if (outputLog)
62 (*outputLog) << "Received message (id " << msg->id << ") of type " << MessageContainer::getMsgTypeString(msg->type) << endl;
63 }
[bace57b]64
[f9cb9fb]65 ackedPlayerMessages[msg->id] = getCurrentMillis();
[855f153]66
[bace57b]67 NETWORK_MSG ack;
68 ack.id = msg->id;
69 ack.type = MSG_TYPE_ACK;
[bd2502a]70
[bace57b]71 sendto(sock, (char*)&ack, sizeof(NETWORK_MSG), 0, (struct sockaddr *)source, sizeof(struct sockaddr_in));
[5a64bea]72
[bace57b]73 if (isDuplicate)
[3794f6d]74 return -1;
[5a64bea]75 }
76
77 return ret;
[1a3c42d]78}
79
[d05086b]80void MessageProcessor::resendUnackedMessages(int sock, ofstream* outputLog) {
[b35b2b2]81 map<unsigned int, map<unsigned long, MessageContainer> >::iterator it;
[bace57b]82 map<unsigned long, MessageContainer>::iterator it2;
83 map<unsigned long, MessageContainer> sentMsg;
84
85 for (it = sentMessages.begin(); it != sentMessages.end(); it++) {
86 sentMsg = it->second;
87 for (it2 = sentMsg.begin(); it2 != sentMsg.end(); it2++) {
[46d6469]88 if (!(it2->second.getAcked())) {
[9fe1807]89 sendto(sock, (const char*)it2->second.getMessage(), sizeof(NETWORK_MSG), 0, (struct sockaddr *)&it2->first, sizeof(struct sockaddr_in));
[46d6469]90 }
[bace57b]91 }
[5a64bea]92 }
[1a3c42d]93}
94
[d05086b]95void MessageProcessor::cleanAckedMessages(ofstream* outputLog) {
[b35b2b2]96 map<unsigned int, map<unsigned long, MessageContainer> >::iterator it = sentMessages.begin();
[bace57b]97 map<unsigned long, MessageContainer>::iterator it2;
[198cf2d]98
[af713bc]99 while (it != sentMessages.end()) {
[bace57b]100 it2 = it->second.begin();
[46d6469]101 while (it2 != it->second.end()) {
102 if (it2->second.getAcked()) {
[d05086b]103 if ((getCurrentMillis() - it2->second.getTimeAcked()) > 1000) {
104 if (outputLog)
105 (*outputLog) << "Removing id " << it2->second.getMessage()->id << " from the acked record" << endl;
[bace57b]106 it->second.erase(it2++);
[d05086b]107 }else
[bace57b]108 it2++;
[6b641af]109 }else
[bace57b]110 it2++;
111 }
112
113 if (it->second.size() == 0)
114 sentMessages.erase(it++);
115 else
[af713bc]116 it++;
[198cf2d]117 }
[4dbac87]118
[f9cb9fb]119 map<unsigned long, map<unsigned int, unsigned long long> >::iterator it3 = ackedMessages.begin();
120 map<unsigned int, unsigned long long>::iterator it4;
[4dbac87]121
[f9cb9fb]122 // somehow want to delete the inner map once that player logs out
[bace57b]123 while (it3 != ackedMessages.end()) {
[f9cb9fb]124 it4 = it3->second.begin();
125 while (it4 != it3->second.end()) {
126 if ((getCurrentMillis() - it4->second) > 500)
127 it3->second.erase(it4++);
128 else
129 it4++;
130 }
131 it3++;
[4dbac87]132 }
[b35b2b2]133}
134
135map<unsigned int, map<unsigned long, MessageContainer> >& MessageProcessor::getSentMessages() {
136 return this->sentMessages;
137}
138
[f9cb9fb]139map<unsigned long, map<unsigned int, unsigned long long> >& MessageProcessor::getAckedMessages() {
[b35b2b2]140 return this->ackedMessages;
[1a3c42d]141}
Note: See TracBrowser for help on using the repository browser.