You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Modelbahn/server/network.cc

280 lines
4.7 KiB

#include <string>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <netdb.h>
#include <errno.h>
#include <syslog.h>
#include <pthread.h>
#include <math.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <sys/wait.h>
#include <sys/syscall.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <list>
#include "modelbahn.h"
#include "network.h"
#include "json.h"
Network::Network() {
thread = 0;
sessions.clear();
thread_running = 0;
mtx = { 0 };
mtx = PTHREAD_MUTEX_INITIALIZER;
}
Network::~Network() {
list<Session*>::iterator iter;
while ((iter = sessions.begin()) != sessions.end()) {
Session *s = *iter;
sessions.remove(*iter);
delete s;
}
Stop();
};
int Network::LockThread() {
if (pthread_mutex_lock(&mtx) == 0) return 1;
else return 0;
}
int Network::UnLockThread() {
if (pthread_mutex_unlock(&mtx) == 0) return 1;
else return 0;
}
void Network::ThreadProcess() {
list<UNIX*>::iterator iteru;
Session *s;
UNIX *u;
while (running) {
//
// check network
//
// server socket
ServerLoop();
//
// client socket
for (iteru = clients.begin(); iteru != clients.end(); iteru++) {
if (ClientLoop((UNIX*) *iteru) < 0) {
u = *iteru;
clients.remove(u);
delete u;
iteru = clients.begin();
}
}
usleep (100000);
}
thread_running = 0;
};
int Network::Start() {
int err;
pthread_attr_t attr;
mtx = { 0 };
mtx = PTHREAD_MUTEX_INITIALIZER;
//
// start socket server
//
if (sockserver.Listen(UNIX_SOCKET_FILE) != 1) {
return 0;
}
chmod(UNIX_SOCKET_FILE, 00666);
thread_running = 1;
pthread_attr_init (&attr);
pthread_attr_setdetachstate (&attr, PTHREAD_CREATE_JOINABLE);
err = pthread_create (&thread, &attr, ThreadEntry, this);
if (err != 0) {
debug (DEBUG_ERROR, (char*)"%s(%s:%d) pthread_create errror: %s", __FUNCTION__, __FILE__, __LINE__, strerror (errno));
running = 0;
return 0;
}
return 1;
};
void Network::Stop() {
sockserver.Close();
unlink(UNIX_SOCKET_FILE);
}
void Network::_ChangeListPushToAll(string changes) {
list<Session*>::iterator iter;
for (iter = sessions.begin(); iter != sessions.end(); iter++) {
if ((*iter)->GetSessionID() > 0) (*iter)->ChangeListPush(changes);
}
};
void Network::ChangeListPushToAll(string changes) {
LockThread();
_ChangeListPushToAll(changes);
UnLockThread();
};
int Network::ServerLoop() {
UNIX *u = NULL;
if (sockserver.IsData(10)) {
u = sockserver.Accept();
clients.push_back(u);
}
return 1;
};
Session *Network::GetSession(int sid) {
Session *s = NULL;
list<Session*>::iterator iter;
for (iter = sessions.begin(); iter != sessions.end(); iter++) {
if ((*iter)->GetSessionID() == sid) {
s = *iter;
break;
}
}
return s;
};
int Network::ClientLoop(UNIX *client) {
char bufferin[BUFFERSIZE];
char bufferout[BUFFERSIZE];
int len, i, rid, sid;
int res;
list<Session*>::iterator siter;
Session *session = NULL;
string value;
string ssid;
string srid;
string s;
int result = -1;
struct timeval timer;
timer_start(&timer);
len = client->ReadTimeout(bufferin, BUFFERSIZE, 20);
if (len > 0 && len < BUFFERSIZE) {
JSONParse json;
JSONParse jsonout;
JSONParse jelement;
bufferin[len] = 0; // prevent reading behind the data
json.Set(bufferin);
if (!json.GetValue("sid", &ssid)) {
debug (0, "json.GetValue error --> sid");
return 0;
}
if (!json.GetValue("rid", &srid)) {
debug (0, "json.GetValue error --> rid");
return 0;
}
//
try {
rid = stoi (srid);
}
catch (...) {
rid = 0;
debug (0, "* rid error");
}
try {
sid = stoi (ssid);
}
catch (...) {
sid = 0;
debug (0, "* sid error");
}
if (sid <= 0) {
int x, y;
debug (0, "* sid not set, gettin new SID");
session = new Session(rid);
sid = session->GetSessionID();
LockThread();
sessions.push_back(session);
UnLockThread();
}
else {
LockThread();
//
// search for session
session = NULL;
for (siter = sessions.begin(); siter != sessions.end(); siter++) {
if ((*siter)->GetRandomID() == rid && ((Session*)(*siter))->GetSessionID() == sid) {
session = (*siter);
break;
}
}
UnLockThread();
}
if (session) {
JSONElement je;
int retval;
LockThread();
retval = session->ProcessData(&json, &jsonout);
UnLockThread();
len = BUFFERSIZE;
if (retval) {
je.Clear();
je.Set("success", 1);
jsonout.AddObject(je);
}
else {
je.Clear();
je.Set("success", 0);
jsonout.AddObject(je);
}
s = jsonout.ToString();
client->Write((char*)s.c_str(), strlen(s.c_str()));
result = 1;
}
else {
// no session found
result = 0;
}
}
else if (len == 0) {
result = 0;
}
return result;
};