18 #include <sys/socket.h> 19 #include <netinet/in.h> 20 #include <netinet/tcp.h> 30 #include <boost/archive/iterators/base64_from_binary.hpp> 31 #include <boost/archive/iterators/transform_width.hpp> 32 #include <boost/archive/iterators/ostream_iterator.hpp> 56 pthread_mutex_init (&deleteMessageMutex, NULL);
60 json_t* result = NULL;
61 pthread_mutex_lock(&deleteMessageMutex);
62 if (!messageList.empty())
64 result = messageList.front();
65 messageList.pop_front();
67 pthread_mutex_unlock(&deleteMessageMutex);
72 struct hostent *server;
73 server = gethostbyname(url.c_str());
78 fprintf(stderr,
"Could not resolve %s.\n",url.c_str());
87 sockfd = socket(AF_INET, SOCK_STREAM, 0);
92 fprintf(stderr,
"Could not create socket.\n");
101 struct sockaddr_in serv_addr;
102 memset(&serv_addr,0,
sizeof(serv_addr));
103 serv_addr.sin_family = AF_INET;
104 bcopy((
char *)server->h_addr,(
char *)&serv_addr.sin_addr.s_addr,server->h_length);
105 serv_addr.sin_port = htons(port);
106 if (connect(sockfd,(
struct sockaddr *) &serv_addr,
sizeof(serv_addr)) < 0)
111 fprintf(stderr,
"Could not connect to %s.\n",url.c_str());
120 pthread_create(&readThread,NULL,run_readAndSetMessages,
this);
132 char* content = json_dumps( *registerMessage, 0 );
151 sprintf(id_string,
"{\"uid\": %i",
id);
152 int add = send(sockfd,id_string,strlen(id_string),MSG_MORE | MSG_NOSIGNAL);
160 uint32_t l = strlen(content)-1;
162 int amount = (l+4095)/4096;
163 for (
int i = 0; i < amount; i++)
167 int add = send(sockfd,&content[i*4096],l - i * 4096,MSG_MORE | MSG_NOSIGNAL);
173 int add = send(sockfd,&content[i*4096],4096,MSG_MORE | MSG_NOSIGNAL);
181 char finisher[] =
"} ";
182 int add = send(sockfd,finisher,2,MSG_NOSIGNAL);
191 this->registerMessage = registerMessage;
192 char* content = json_dumps( *registerMessage, 0 );
199 static void isaac_init_destination(j_compress_ptr cinfo)
202 static boolean isaac_jpeg_empty_output_buffer(j_compress_ptr cinfo)
206 static void isaac_jpeg_term_destination(j_compress_ptr cinfo)
212 if (jpeg_quality > 100)
214 this->jpeg_quality = jpeg_quality;
219 uint32_t count = width*height*depth;
221 struct jpeg_compress_struct cinfo;
222 struct jpeg_error_mgr jerr;
223 jpeg_destination_mgr dest;
224 dest.init_destination = &isaac_init_destination;
225 dest.empty_output_buffer = &isaac_jpeg_empty_output_buffer;
226 dest.term_destination = &isaac_jpeg_term_destination;
227 cinfo.err = jpeg_std_error(&jerr);
228 jpeg_create_compress(&cinfo);
230 std::vector<char> jpeg_buffer;
231 jpeg_buffer.resize( count );
232 cinfo.dest->next_output_byte = (JOCTET*)(jpeg_buffer.data());
233 cinfo.dest->free_in_buffer = count;
234 cinfo.image_width = width;
235 cinfo.image_height = height;
236 cinfo.input_components = depth;
237 cinfo.in_color_space = JCS_EXT_RGBX;
238 jpeg_set_defaults(&cinfo);
239 jpeg_set_quality(&cinfo, jpeg_quality,
false);
240 jpeg_start_compress(&cinfo, TRUE);
241 while (cinfo.next_scanline < cinfo.image_height)
243 JSAMPROW row_pointer[1];
244 row_pointer[0] = & ((JSAMPROW)ptr)[cinfo.next_scanline * width * depth];
245 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
247 jpeg_finish_compress(&cinfo);
248 count -= cinfo.dest->free_in_buffer;
249 ptr = jpeg_buffer.data();
250 jpeg_destroy_compress(&cinfo);
253 using namespace boost::archive::iterators;
254 std::stringstream payload;
260 const unsigned char *,
268 base64_text( (
char*)ptr ),
269 base64_text( (
char*)ptr + count),
270 boost::archive::iterators::ostream_iterator<char>(payload)
274 char header[] =
"{\"payload\": \"data:image/jpeg;base64,";
276 char header[] =
"{\"payload\": \"data:image/raw-rgba;base64,";
278 char footer[] =
"\"}";
279 int hl = strlen(header);
280 int pl = payload.str().length();
281 int fl = strlen(footer);
282 #if ISAAC_VALGRIND_TWEAKS == 1 287 char* message = (
char*)malloc(hl+pl+fl+1+4);
289 char* message = (
char*)malloc(hl+pl+fl+1);
291 memcpy( message ,header,hl);
292 memcpy(&(message[hl ]),payload.str().c_str(),pl);
293 memcpy(&(message[hl+pl]),footer,fl+1);
306 pthread_cancel(readThread);
307 pthread_mutex_destroy(&deleteMessageMutex);
310 void readAndSetMessages()
312 while (json_t * content = json_load_callback(json_load_callback_function,&sockfd,JSON_DISABLE_EOF_CHECK,NULL))
316 if (js = json_object_get( content,
"fatal error"))
318 const char* fatal_error = json_string_value( js );
319 fprintf(stderr,
"Fatal error: \"%s\".\n",fatal_error);
320 if (strcmp(fatal_error,
"protocol mismatch") == 0)
325 json_decref( content );
328 if (js = json_object_get( content,
"done"))
330 isaac_uint new_server_id = json_integer_value( js );
331 if (new_server_id > server_id)
332 server_id = new_server_id;
333 json_decref( content );
337 pthread_mutex_lock(&deleteMessageMutex);
338 messageList.push_back(content);
339 pthread_mutex_unlock(&deleteMessageMutex);
343 static size_t json_load_callback_function (
void *buffer,
size_t buflen,
void *data)
345 return recv(*((
isaac_int*)data),buffer,1,0);
347 static void* run_readAndSetMessages(
void* communicator)
358 std::list<json_t*> messageList;
359 pthread_mutex_t deleteMessageMutex;
360 pthread_t readThread;
361 json_t** registerMessage;
IsaacCommunicator(const std::string url, const isaac_uint port)
isaac_int serverSend(char *content, bool starting=true, bool finishing=false)
json_t * getLastMessage()
#define ISAAC_MAX_DIFFERENCE
void setJpegQuality(isaac_uint jpeg_quality)
void serverSendFrame(void *ptr, const isaac_uint width, const isaac_uint height, const isaac_uint depth)
isaac_int serverSendRegister(json_t **registerMessage)
#define ISAAC_HANDLE_EPIPE(add, n, sockfd, readThread)
isaac_int serverConnect(CommunicatorSetting setting)