memcpy(&sendbuffer[size],(void*)&tp, sizeof(struct timeval));
size += sizeof(struct timeval);
pthread_mutex_lock(&po_mutex);
+ cout << "position x: " << position.x << "\n";
float x = position.x;
+ cout << "x: " << x << "\n";
float z = position.z;
- memcpy(&sendbuffer[size],(void*)&x, sizeof(int));
- size += sizeof(int);
- memcpy(&sendbuffer[size],(void*)&z, sizeof(int));
- size += sizeof(int);
+ cout << "position z: " << position.z << "\n";
+ cout << "z: " << z << "\n";
+ memcpy(&sendbuffer[size],(void*)&x, sizeof(float));
+ size += sizeof(float);
+ memcpy(&sendbuffer[size],(void*)&z, sizeof(float));
+ size += sizeof(float);
memcpy(&sendbuffer[size],(void*)&orientation, sizeof(Quaternion));
pthread_mutex_unlock(&po_mutex);
size += sizeof(Quaternion);
memcpy(&tp,&recvbuffer[sizeread], sizeof(struct timeval));
sizeread += sizeof(struct timeval);
float x,z;
- memcpy(&x,&recvbuffer[sizeread], sizeof(int));
- sizeread += sizeof(int);
- memcpy(&z,&recvbuffer[sizeread], sizeof(int));
- sizeread += sizeof(int);
+ memcpy(&x,&recvbuffer[sizeread], sizeof(float));
+ sizeread += sizeof(float);
+ memcpy(&z,&recvbuffer[sizeread], sizeof(float));
+ sizeread += sizeof(float);
pos.x = x;
pos.y = 100.5;
pos.z = z;
{
if (player->id == newUpdate.id && !player->dead)
{
- /* if (player->posupdates_log.size() > 0)
- {
- Vector3 prevPos = player->posupdates_log.front();
- // Vector3 prevPos = player->_getDerivedPosition();
- Real distance = prevPos.distance(newUpdate.pos);
- if (distance > 0)
- {
- Vector3 curPos = player->playerNode->_getDerivedPosition();
- Vector3 direction = newUpdate.pos.operator-(curPos);
- direction.normalise();
- struct timeval diff;
- struct timeval now;
- gettimeofday(&now, NULL);
- timersub(&now, &newUpdate.timestamp, &diff);
- Real timeSinceLastUpdate = diff.tv_sec + diff.tv_usec*0.000001;
- cout << "time since last update ms" << timeSinceLastUpdate <<"\n";
- Vector3 correctedPos = newUpdate.pos.operator+(direction.operator*(SPEED_PER_SECOND*timeSinceLastUpdate));
- if (!collision(correctedPos))
- newUpdate.pos = correctedPos;
- }
- else if(distance < 0)
- {
- cout << "strange distance!\n";
- cout << "current position: " << prevPos << "\n";
- cout << "update: " << newUpdate.pos << "\n";
- cout << "distance: " << distance << "\n";
- }
- }*/
player->setStateUpdate(newUpdate.timestamp, newUpdate.pos, newUpdate.orient);
break;
}
--- /dev/null
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <resolv.h>
+#include <arpa/inet.h>
+#include <pthread.h>
+
+#define SERV_PORT 5001
+#define NUM_PLAYERS 10
+#define PBUF_SZ 44 // size of the message received by client
+#define SBUF_SZ (NUM_PLAYERS*PBUF_SZ) // maximum size of the buffer sent to clients
+
+struct client {
+ int id;
+ int socket;
+ char data[PBUF_SZ];
+ char nickname[12];
+ bool newUpdate;
+ bool hasNickname;
+ pthread_mutex_t mutex;
+ struct client* next;
+ struct client* prev;
+};
+
+typedef struct client clientState;
+
+void* SocketReader(void* client);
+void* BufferHandler(void* head);
+int AssignID(int* IDtable);
+void removeClient(clientState* client);
+void addClient(clientState* client);
+
+clientState* client_head;
+
+int sessionid;
+
+pthread_mutex_t client_list_m;
+
+pthread_mutex_t active_players_m;
+pthread_cond_t active_players;
+
+
+int main(int argv, char** argc){
+
+ int serv_port = SERV_PORT;
+
+ if (argv < 3)
+ {
+ printf("usage: ./server <port> <session nr>\n");
+ return 1;
+ }
+
+ serv_port = atoi(argc[1]);
+ sessionid = atoi(argc[2]);
+
+
+
+ printf("Starting server on port %d\n", serv_port);
+
+ int IDtable[NUM_PLAYERS];
+
+
+ struct sockaddr_in serv_addr;
+ int hostSocket;
+ int p_int = 1;
+ socklen_t addr_size = 0;
+ struct sockaddr_in sadr;
+
+
+
+ hostSocket = socket(AF_INET, SOCK_STREAM, 0);
+ if(hostSocket == -1){
+ printf("Error initializing socket %d\n", errno);
+ return 1;
+ }
+
+ if( (setsockopt(hostSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&p_int, sizeof(int)) == -1 )||
+ (setsockopt(hostSocket, SOL_SOCKET, SO_KEEPALIVE, (char*)&p_int, sizeof(int)) == -1 ) ){
+ printf("Error setting options %d\n", errno);
+ return 1;
+ }
+
+ serv_addr.sin_family = AF_INET ;
+ serv_addr.sin_port = htons(serv_port);
+
+ memset(&(serv_addr.sin_zero), 0, 8);
+ serv_addr.sin_addr.s_addr = INADDR_ANY ;
+
+ if( bind( hostSocket, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1 ){
+ fprintf(stderr,"Error binding to socket, make sure nothing else is listening on this port %d\n",errno);
+ return 1;
+ }
+ if(listen(hostSocket, 10) == -1 ){
+ fprintf(stderr, "Error listening %d\n",errno);
+ return 1;
+ }
+
+ addr_size = sizeof(struct sockaddr_in);
+
+ pthread_t thread_id = 0;
+ pthread_mutex_init(&active_players_m, NULL);
+ pthread_cond_init(&active_players, NULL);
+
+ pthread_create(&thread_id,0,&BufferHandler, (void*)client_head);
+ pthread_detach(thread_id);
+
+ pthread_mutex_init(&client_list_m, NULL);
+
+ clientState* client;
+
+ while(1)
+ {
+ printf("Waiting for players to connect.\n");
+
+
+ int csock;
+ if((csock = accept(hostSocket, (struct sockaddr*)&sadr, &addr_size))!= -1)
+ {
+ client = (clientState*)malloc(sizeof(clientState));
+ client->socket = csock;
+ memset(client->data, 0, PBUF_SZ);
+ memset(client->nickname, 0, 12);
+ client->newUpdate = false;
+ client->hasNickname = false;
+ pthread_mutex_init(&client->mutex, NULL);
+ client->next = NULL;
+ client->prev = NULL;
+ printf("---------------------------\nReceived connection from %s\n---------------------------\n",
+ inet_ntoa(sadr.sin_addr));
+
+ client->id = AssignID(IDtable);
+ addClient(client);
+
+ pthread_create(&thread_id,0,&SocketReader, (void*)client);
+ pthread_detach(thread_id);
+ }
+ else
+ fprintf(stderr, "Error accepting %d\n", errno);
+ }
+}
+
+
+void* SocketReader(void* client){
+
+ int bytes;
+ char buffer[PBUF_SZ];
+ clientState* myState = (clientState*)client;
+
+ printf("---------------------------\nPlayer %d has joined.\n---------------------------\n",
+ myState->id);
+
+ //send ID to the client
+ if((bytes = send(myState->socket, (char*)&(myState->id), sizeof(int),0)) < 1)
+ {
+ printf("Error sending ID to player %d.\n",myState->id);
+ return 0;
+ }
+
+ if((bytes = send(myState->socket, (char*)&(sessionid), sizeof(int),0)) < 1)
+ {
+ printf("Error sending session ID to player %d.\n",myState->id);
+ return 0;
+ }
+
+ while(1)
+ {
+ memset(buffer, 0, PBUF_SZ);
+ bytes = recv(myState->socket, buffer, PBUF_SZ, 0);
+ if(bytes < 2)
+ {
+ printf("Player %d has left.\n", myState->id);
+ removeClient(myState);
+ return 0;
+ }
+ // received a nickname
+ else if(bytes >1 && bytes <= 12)
+ {
+ printf("---------------------------\nPlayer %d: Received nickname.\n---------------------------\n",
+ myState->id);
+ pthread_mutex_lock(&myState->mutex);
+ memcpy(myState->nickname, buffer, 12);
+ myState->hasNickname = true;
+ pthread_mutex_unlock(&myState->mutex);
+ }
+ else
+ {
+ pthread_mutex_lock(&myState->mutex);
+
+ memcpy(myState->data, buffer, PBUF_SZ);
+ myState->newUpdate = true;
+ pthread_mutex_unlock(&myState->mutex);
+
+ printf("---------------------------\nPlayer %d: Received %d bytes.\n---------------------------\n",
+ myState->id, bytes);
+ }
+
+
+ }
+}
+
+void* BufferHandler(void* head)
+{
+ int bytes;
+ int bufferLength = 0;
+ char sendbuffer[SBUF_SZ];
+
+ while(1)
+ {
+ if (client_head == NULL)
+ {
+ sessionid++;
+ printf("0 active players, waiting for signal.\n");
+ pthread_mutex_lock(&active_players_m);
+ pthread_cond_wait(&active_players, &active_players_m);
+ pthread_mutex_unlock(&active_players_m);
+ }
+
+ int curPos = 0;
+ curPos += sizeof(int); // reserve space for message size
+ memset(sendbuffer, 0, SBUF_SZ);
+
+ clientState* client;
+
+ for (client = client_head; client != NULL; client = client->next)
+ {
+ // need to try lock first because it can be locked by removeClient
+ int res = pthread_mutex_trylock(&client->mutex);
+ if (res != 0)
+ continue;
+
+ if (client->newUpdate)
+ {
+ client->newUpdate = false;
+ memcpy(&sendbuffer[curPos], &client->id, sizeof(int));
+ curPos += sizeof(int);
+ memcpy(&sendbuffer[curPos], client->data, PBUF_SZ);
+ curPos += PBUF_SZ;
+ }
+ pthread_mutex_unlock(&client->mutex);
+ }
+
+ // if there are any updates, send them to all players
+ if (curPos >= (int)(PBUF_SZ+sizeof(int)))
+ {
+ bufferLength = curPos;
+ int size = bufferLength - sizeof(int);
+ memcpy(&sendbuffer[0], &size, sizeof(int));
+
+ clientState* client;
+ pthread_mutex_lock(&client_list_m);
+ for (client = client_head; client != NULL; client = client->next)
+ {
+ if((bytes = send(client->socket, &sendbuffer[0], bufferLength,0)) == -1)
+ fprintf(stderr, "Error sending data %d\n", errno);
+ else
+ printf("Sent %d bytes to player %d.\n", bytes, client->id);
+
+ // send nickname
+ }
+ pthread_mutex_unlock(&client_list_m);
+ }
+
+ }
+ return 0;
+}
+
+int AssignID(int* IDtable)
+{
+ if (client_head == NULL)
+ memset(IDtable, 0, sizeof(int)*NUM_PLAYERS);
+
+ int i;
+ for (i = 0; i < NUM_PLAYERS; i++)
+ {
+ if (IDtable[i] != 1)
+ {
+ IDtable[i] = 1;
+ return i;
+ }
+ }
+ return -1;
+}
+
+
+void removeClient(clientState* client)
+{
+ pthread_mutex_lock(&client_list_m);
+ clientState* prev = client->prev;
+ clientState* next = client->next;
+ free(client);
+
+ if (prev == NULL) // removed client was head
+ {
+ client_head = next;
+ if (client_head != NULL)
+ client_head->prev = NULL;
+ }
+ else if (next == NULL) // removed client was last in the list
+ prev->next = NULL;
+ else
+ {
+ prev->next = next;
+ next->prev = prev;
+ }
+ pthread_mutex_unlock(&client_list_m);
+}
+
+void addClient(clientState* client)
+{
+ pthread_mutex_lock(&client_list_m);
+ clientState* current = client_head;
+
+ if (client_head == NULL)
+ {
+ client_head = client;
+ pthread_cond_signal(&active_players);
+ }
+ else
+ {
+ while(current->next != NULL)
+ current = current->next;
+
+ client->prev = current;
+ current->next = client;
+ }
+ pthread_mutex_unlock(&client_list_m);
+}
+
+