//
// ElectroCraftCommunicationClient.cpp
//
//
// Created by Andrew Querol on 8/2/12.
//
//
#include "ElectroCraftCommunicationClient.h"
// Unix Includes
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <pthread.h>
// QEMU Includes
#include "qemu-common.h"
#include "console.h"
#include "sysemu.h"
// ElectroCraft Server Stuff
char* commsChannel; // The "channel" (Username) of the client we are talking to
int serverPort;
char *serverAddress;
pthread_t clientThread;
bool running = false;
bool started = false;
int sockfd;
pthread_mutex_t socketMutex;
// Declare our run method
void* run(void* args);
// Server Protocol
enum Protocol {
DISPLAY = 0,
INPUT = 1
};
// QEMU
static DisplayChangeListener *dcl;
static void electrocraft_cleanup(void) {
printf("ElectroCraft QEMU Server: Cleanup Called");
g_free(dcl);
pthread_exit(NULL);
}
static void electrocraft_update(DisplayState *ds, int x, int y, int w, int h) {
}
static void electrocraft_resize(DisplayState *ds) {
}
static void electrocraft_refresh(DisplayState *ds) {
if (started) {
//pthread_mutex_lock(&socketMutex);
int numberOfPixels = ds->surface->width * ds->surface->height;
unsigned char* data = (unsigned char*)malloc(((numberOfPixels * 3) * sizeof(unsigned char)) + sizeof(unsigned char) + sizeof(int));
data[0] = DISPLAY;
data[1] = numberOfPixels & 0xFF;
data[2] = (numberOfPixels >> 8) & 0xFF;
data[3] = (numberOfPixels >> 16) & 0xFF;
data[4] = (numberOfPixels >> 24) & 0xFF;
printf("Number of pixles %d\n", numberOfPixels);
int byteNumber = 5, i = 0;
for (; i < numberOfPixels; i++) {
data[byteNumber++] = (unsigned char)ds->surface->data[i] >> 16;
data[byteNumber++] = (unsigned char)ds->surface->data[i] >> 8;
data[byteNumber++] = (unsigned char)ds->surface->data[i];
}
write(sockfd, data, ((numberOfPixels * 3) * sizeof(unsigned char)) + sizeof(unsigned char) + sizeof(int));
//pthread_mutex_unlock(&socketMutex);
}
vga_hw_update();
}
void electrocraft_init(DisplayState *ds) {
// Initialize our socket mutex
pthread_mutex_init(&socketMutex, NULL);
dcl = g_malloc0(sizeof(DisplayChangeListener));
// register vga output callbacks
dcl->dpy_update = electrocraft_update;
dcl->dpy_resize = electrocraft_resize;
dcl->dpy_refresh = electrocraft_refresh;
register_displaychangelistener(ds, dcl);
// register cleanup function
atexit(electrocraft_cleanup);
}
void electroCraftConnect(int port, char* address, char* channel) {
commsChannel = channel;
serverPort = port;
serverAddress = address;
running = true;
int rc = pthread_create(&clientThread, NULL, run, NULL);
if (rc){
printf("ElectroCraft Qemu: Error, return code from pthread_create() is %d\n", rc);
exit(EXIT_FAILURE);
}
}
void* run(void* args) {
int bytesRead;
struct sockaddr_in serv_addr;
struct hostent *server;
unsigned char buffer[256];
server = gethostbyname(serverAddress);
memset(&serv_addr, 0, sizeof(struct sockaddr_in));
memcpy((char *)&serv_addr.sin_addr, server->h_addr, server->h_length);
serv_addr.sin_family = server->h_addrtype;
serv_addr.sin_port = htons(serverPort);
sockfd = socket(server->h_addrtype, SOCK_STREAM, 0);
if (sockfd < 0) {
printf("ElectroCraft Qemu: Error opening socket!\n");
exit(EXIT_FAILURE);
}
if (connect(sockfd, &serv_addr, sizeof(serv_addr)) < 0) {
printf("ElectroCraft Qemu: Error connecting!\n");
exit(EXIT_FAILURE);
}
printf("ElectroCraft Qemu: Connected to the JAVA server!\n");
while (running) {
started = true;
pthread_mutex_lock(&socketMutex);
//bytesRead = read(sockfd, buffer, 1);
if (bytesRead < 0) {
//running = false;
} else if (bytesRead > 0) {
unsigned char code = buffer[0];
bzero(buffer, 256);
switch (code) {
case 0:
break;
default:
printf("ElectroCraft Qemu: Got unknown packet!\n");
break;
}
bzero(buffer, 256);
}
pthread_mutex_unlock(&socketMutex);
}
printf("ElectroCraft Qemu: Disconnected from the JAVA server!\n");
return EXIT_SUCCESS;
}