forest-net
an overlay networks for large-scale virtual worlds
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator
AvatarServer.cpp
1 #include "Np4d.h"
2 #include "NetBuffer.h"
3 #include <map>
4 #include <iostream>
5 #include <fstream>
6 #include <sstream>
7 #include <string>
8 #include <pthread.h>
9 
10 #define CHUNK 1024
11 using namespace forest;
12 
13 /*
14  * usage: avatarServer
15  * This script handles requests from users to save and download avatar files.
16  * 09/25: download done, separated send_file
17  */
18 
19 void handleClient(int);
20 void* handler(void*);
21 
22 int main() {
23  // open stream socket and bind to port 30124
24 
25  int listenSock = Np4d::streamSocket();
26  if (listenSock < 0) fatal("can't create socket");
27  ipa_t myIP = Np4d::myIpAddress();
28  if (!Np4d::bind4d(listenSock, INADDR_ANY, 30125)) fatal("can't bind socket");
29 
30  // prepare to accept connections
31  if (!Np4d::listen4d(listenSock)) fatal("error on listen");
32  while (true) {
33  // wait for incoming connection request and create new socket
34  int connSock = Np4d::accept4d(listenSock); //
35  std::cout << connSock << "connected" << std::endl;
36  if (connSock < 0) fatal("error on accept"); //include? for fatal
37 
38  // start a separate thread to handle this socket
39  handleClient(connSock);
40  }
41 }
42 
43 void handleClient(int sock) {
44  pthread_t thisThread;
45  int* sockp = new int;
46  *sockp = sock;
47 
48  pthread_attr_t attr; pthread_attr_init(&attr);
49  pthread_attr_setstacksize(&attr,4*PTHREAD_STACK_MIN);
50  pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
51  if (pthread_create(&thisThread, &attr, &(handler), (void *) sockp) != 0)
52  fatal("cannot create thread");
53 }
54 
55 void sendFile(string fileName, int sock)
56 {
57  ifstream pFile (fileName.c_str(), ios::in | ios::binary | ios::ate);
58 
59  ifstream::pos_type size;
60  char *memblock;
61 
62  if(pFile.is_open())
63  {
64  //std::cout << "file opened" << std::endl;
65  size = pFile.tellg();
66  memblock = new char [size];
67  pFile.seekg (0, ios::beg);
68  pFile.read(memblock, size);
69  //complete file in its binary form is now in memory
70  pFile.close();
71  int bufSize = (int)size;
72  //std::cout << bufSize << std::endl;
73  stringstream ss;
74  ss << "success:" << bufSize;
75  string echo = ss.str();
76  while (echo.size() < 14)
77  {
78  echo += " ";
79  }
80  echo += '/n';
81  Np4d::sendString(sock, echo);
82  char * ap = &memblock[0];
83 
84  //send from memblock 1024 bytes at a time
85  while(bufSize >= CHUNK)
86  {
87  Np4d::sendBufBlock(sock, ap, CHUNK);
88  ap += CHUNK;
89  bufSize -= CHUNK;
90  }
91  // if last chunk less than CHUNK bytes (1024 for now)
92  if(bufSize > 0)
93  {
94  Np4d::sendBufBlock(sock, ap, bufSize);
95  }
96 
97  //de-allocate memory
98  delete[] memblock;
99  }
100  else {
101  //std::cout << "didn't open" << std::endl;
102  Np4d::sendString(sock,"failure:00404\n");
103  close(sock); return NULL;
104  }
105 
106 
107 }
108 
109 void* handler(void* sockp) {
110 
111  int sock = *((int *) sockp); delete ((int *) sockp);
112  string fileName;
113  NetBuffer buf(sock, 1024);
114  string s1;
115  string pkt_type;
116 
117  if (buf.readAlphas(s1)) {
118  if (s1 == "getAvatar") { pkt_type = "get"; }
119  else if (s1 == "getTexture") { pkt_type = "getTex"; }
120  else
121  {
122  Np4d::sendString(sock,"unrecognized input, should've been a getAvatar request.\noverAndOut\n");
123  close(sock); return NULL;
124  }
125  }
126 
127  //process a getAvatar request by looking up files and send them
128  if (pkt_type == "get")
129  {
130  if (buf.verify(':'))
131  {
132  string s2;
133  if (buf.readAlphas(s2) && s2 != ""){
134  // get the egg files first
135  fileName = string("clientAvatars/") + s2 + string(".zip");
136  std::cout << fileName << std::endl;
137  sendFile(fileName, sock);
138 
139  //then, send texture file
140  if(buf.verify(':'))
141  {
142  string s3;
143  string tex_file_type;
144  if (buf.readAlphas(s3) && s3 != "")
145  {
146  switch (s3){
147  case "H": tex_file_type = string(".png");
148  case "M": tex_file_type = string(".jpg");
149  case "L": tex_file_type = string("_lo.jpg");
150  default: tex_file_type = string(".jpg");
151  }
152  }
153  string tex_to_send = string("clientTextures/") + s2 + tex_file_type;
154  sendFile(tex_to_send, sock);
155  }
156  else
157  {
158  Np4d::sendString(sock,"unrecognized input, missing : (colon)\n"
159  "overAndOut\n");
160  close(sock); return NULL;
161  }
162  }
163  else
164  {
165  //std::cout << "hmmmm" << std::endl;
166  Np4d::sendString(sock,"unrecognized input, missing : (username)\n"
167  "overAndOut\n");
168  close(sock); return NULL;
169  }
170  }
171  else
172  {
173  //std::cout << "hmmmm" << std::endl;
174  Np4d::sendString(sock,"unrecognized input, missing : (colon)\n"
175  "overAndOut\n");
176  close(sock); return NULL;
177  }
178  }
179  else
180  {
181  /send texture file
182  if(buf.verify(':'))
183  {
184  string s3;
185  string tex_file_type;
186  if (buf.readAlphas(s3) && s3 != "")
187  {
188  switch (s3){
189  case "H": tex_file_type = string(".png");
190  case "M": tex_file_type = string(".jpg");
191  case "L": tex_file_type = string("_lo.jpg");
192  default: tex_file_type = string(".jpg");
193  }
194  }
195  string tex_to_send = string("clientTextures/") + s2 + tex_file_type;
196  sendFile(tex_to_send, sock);
197  }
198  else
199  {
200  Np4d::sendString(sock,"unrecognized input, missing : (colon)\n"
201  "overAndOut\n");
202  close(sock); return NULL;
203  }
204 
205 
206  }
207 
208  close(sock); return NULL;
209 }