Skip to content

Instantly share code, notes, and snippets.

@idimiter
Last active May 26, 2016 18:18
Show Gist options
  • Save idimiter/63fef9ed910b864b2870292c29d933b4 to your computer and use it in GitHub Desktop.
Save idimiter/63fef9ed910b864b2870292c29d933b4 to your computer and use it in GitHub Desktop.
Unity Transport UDP Layer basic echo server
//
// unet_udp.c
// Unity Transport UDP Layer basic echo server
//
// Created by Dimitar Dimitrov on 12/27/15.
// Copyright © 2015 Dimitar Dimitrov. All rights reserved.
//
#include <stdlib.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 3000
#define MAX_BYTES 512
// NOTE:: I could not figure the packing method for the type of the packets
// First three bytes might be dynamic bit fields or packet values
//
enum NetworkEventType {
DataEvent = 2, //= 0,
ConnectEvent = 1, //= 1,
DisconnectEvent = 3, //= 2,
Nothing = 4, //= 3,
BroadcastEvent = 9, //= 4
Unknown = -1
};
NetworkEventType get_type(char *p, size_t sz) {
if (p[0] != 0)
return Unknown;
if (sz > 1 && p[1] != 0)
return DataEvent;
return (NetworkEventType)p[2];
}
void debug_packet(char *p, size_t sz) {
for (int i = 0; i < sz; i++)
printf("%02hhx ", p[i]);
printf("\n");
}
int main(int argc, char **argv) {
int s; // socket descriptor
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(struct sockaddr);;
ssize_t bytes_recieved = 1;
char buf[MAX_BYTES];
if((s = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Error socket()");
exit(-1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;
memset(&(server_addr.sin_zero), 0, 8);
if(bind(s, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) != 0) {
perror("Error bind()");
exit(-1);
}
printf("Waiting for connections...\n");
while (bytes_recieved > 0) {
if( (bytes_recieved = recvfrom(s, buf, MAX_BYTES - 1, 0, (struct sockaddr *)&client_addr, &addr_len)) < 0 ) {
perror("Error recvfrom()");
close(s);
exit(-1);
}
buf[bytes_recieved] = 0;
NetworkEventType type = get_type(buf, bytes_recieved);
// debug_packet(buf, numbytes);
switch (type) {
case Nothing:
sendto(s, buf, bytes_recieved, 0, (struct sockaddr *)&client_addr, addr_len);
break;
case DataEvent:
// 9 bytes offset ONLY for QoS Unreliable!!!
if (bytes_recieved > 10)
printf("%s: %s\n", inet_ntoa(client_addr.sin_addr), buf + 9);
sendto(s, buf, bytes_recieved, 0, (struct sockaddr *)&client_addr, addr_len);
break;
case ConnectEvent:
printf("Client connect: %s\n", inet_ntoa(client_addr.sin_addr));
sendto(s, buf, bytes_recieved, 0, (struct sockaddr *)&client_addr, addr_len);
break;
case DisconnectEvent:
printf("Client Disconnected: %s\n", inet_ntoa(client_addr.sin_addr));
break;
case BroadcastEvent:
printf("Received Broadcast: %s\n", inet_ntoa(client_addr.sin_addr));
break;
default:
fprintf(stderr, "Unhandled enum value %d!\n", type);
printf("%s", buf);
sendto(s, buf, bytes_recieved, 0, (struct sockaddr *)&client_addr, addr_len);
break;
}
usleep(10000);
}
close(s);
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment