/* * Copyright 2010 Nathan Phillip Brink * * This file is a part of DistRen. * * DistRen is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * DistRen is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with DistRen. If not, see . */ #include "common/config.h" #include "libdistren.h" #include "common/protocol.h" #include "common/remoteio.h" #include "common/request.h" static void handle_ping(struct remoteio *rem, struct distren_request *req, void *req_data); static void handle_version(distren_t distren, struct distren_request *req, void *req_data); static void handle_disconnect(distren_t distren, struct remoteio *rem, struct distren_request *req, void *req_data); size_t libdistren_remoteio_read_handle(struct remoteio *rem, void *garbage, void *buf, size_t len, distren_t distren) { size_t to_return; size_t last_len; short err; struct distren_request *req; void *req_data; to_return = 0; while(!distren->done_ad) { if(!len) return to_return; putchar(*(char *)buf); if(*(char *)buf == '\n') distren->done_ad = 1; len --; to_return ++; buf ++; } /* hack to get into the loop at all ;-) */ last_len = 1; while(last_len) { last_len = distren_request_handle(NULL, buf, len, &req, &req_data, &err); if(err) { remoteio_close(rem); return to_return; } if(!last_len) return to_return; switch((enum distren_request_type)req->type) { case DISTREN_REQUEST_PING: handle_ping(rem, req, req_data); break; case DISTREN_REQUEST_VERSION: handle_version(distren, req, req_data); break; case DISTREN_REQUEST_DISCONNECT: handle_disconnect(distren, rem, req, req_data); break; default: /* * we don't implement everything because we don't need to do * so. But, we should complain when we get something we * don't recognize because... server protocols change * ;-). Oh, and when I'm first writing this, this * block will be hit a lot ;-). */ fprintf(stderr, "Unrecognized request type: %lu\n", (unsigned long)req->type); break; } distren_request_free(req); buf += last_len; len -= last_len; } return to_return; } void libdistren_remoteio_close_handle(void *garbage, distren_t distren) { distren->rem = NULL; } /* handlers */ static void handle_ping(struct remoteio *rem, struct distren_request *req, void *req_data) { struct distren_request *pong_req; void *pong_req_data; distren_request_poing(&pong_req, &pong_req_data, 0, req_data, req->len); distren_request_send(rem, pong_req, pong_req_data); distren_request_free_with_data(pong_req, pong_req_data); } static void handle_version(distren_t distren, struct distren_request *req, void *req_data) { struct distren_request_version version; int tmp; tmp = distren_request_parse_version(req, req_data, &version); if(tmp) { fprintf(stderr, "error: Invalid DISTREN_REQUEST_VERSION, disconnecting from server\n"); /* * our remoteio_close handler sets distren->rem to NULL, thus we * don't need to return an error code. */ remoteio_close(distren->rem); return; } distren->servertype = version.servertype; distren->state = DISTREN_STATE_AUTH; fprintf(stderr, "info: connected to a server running %s\n", version.package_string); if(version.servertype & DISTREN_SERVERTYPE_CLIENT) fprintf(stderr, "\tis a client\n"); if(version.servertype & DISTREN_SERVERTYPE_SUBMIT) fprintf(stderr, "\taccepts frame submissions\n"); if(version.servertype & DISTREN_SERVERTYPE_RENDER) fprintf(stderr, "\trenders frames\n"); if(version.servertype & DISTREN_SERVERTYPE_DISTRIBUTE) fprintf(stderr, "\thandles file distribution\n"); } static void handle_disconnect(distren_t distren, struct remoteio *rem, struct distren_request *req, void *req_data) { size_t tmp; fputs("warning: The server has disconnected us because ``", stderr); tmp = fwrite(req_data, 1, req->len, stderr); fputs("''\n", stderr); remoteio_close(distren->rem); }