Last active
May 26, 2016 18:18
-
-
Save idimiter/63fef9ed910b864b2870292c29d933b4 to your computer and use it in GitHub Desktop.
Unity Transport UDP Layer basic echo server
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// 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