static void TestPictureTypefaceSerialization(skiatest::Reporter* reporter) { { // Load typeface from file to test CreateFromFile with index. SkString filename = GetResourcePath("/fonts/test.ttc"); sk_sp<SkTypeface> typeface(SkTypeface::MakeFromFile(filename.c_str(), 1)); if (!typeface) { INFOF(reporter, "Could not run fontstream test because test.ttc not found."); } else { serialize_and_compare_typeface(std::move(typeface), "A!", reporter); } } { // Load typeface as stream to create with axis settings. SkAutoTDelete<SkStreamAsset> distortable(GetResourceAsStream("/fonts/Distortable.ttf")); if (!distortable) { INFOF(reporter, "Could not run fontstream test because Distortable.ttf not found."); } else { SkFixed axis = SK_FixedSqrt2; sk_sp<SkTypeface> typeface(SkTypeface::MakeFromFontData( new SkFontData(distortable.release(), 0, &axis, 1))); if (!typeface) { INFOF(reporter, "Could not run fontstream test because Distortable.ttf not created."); } else { serialize_and_compare_typeface(std::move(typeface), "abc", reporter); } } } }
static void TestPictureTypefaceSerialization(skiatest::Reporter* reporter) { { // Load typeface from file to test CreateFromFile with index. auto data = GetResourceAsData("fonts/test.ttc"); auto typeface = SkTypeface::MakeFromStream(new SkMemoryStream(std::move(data)), 1); if (!typeface) { INFOF(reporter, "Could not run fontstream test because test.ttc not found."); } else { serialize_and_compare_typeface(std::move(typeface), "A!", reporter); } } { // Load typeface as stream to create with axis settings. std::unique_ptr<SkStreamAsset> distortable(GetResourceAsStream("fonts/Distortable.ttf")); if (!distortable) { INFOF(reporter, "Could not run fontstream test because Distortable.ttf not found."); } else { SkFixed axis = SK_FixedSqrt2; sk_sp<SkTypeface> typeface(SkTypeface::MakeFromFontData( skstd::make_unique<SkFontData>(std::move(distortable), 0, &axis, 1))); if (!typeface) { INFOF(reporter, "Could not run fontstream test because Distortable.ttf not created."); } else { serialize_and_compare_typeface(std::move(typeface), "abc", reporter); } } } }
void rhizome_server_poll(struct sched_ent *alarm) { if (alarm->poll.revents & (POLLIN | POLLOUT)) { struct sockaddr addr; unsigned int addr_len = sizeof addr; int sock; while ((sock = accept(rhizome_server_socket, &addr, &addr_len)) != -1) { if (addr.sa_family == AF_INET) { struct sockaddr_in *peerip = (struct sockaddr_in *)&addr; INFOF("RHIZOME HTTP SERVER, ACCEPT addrlen=%u family=%u port=%u addr=%u.%u.%u.%u", addr_len, peerip->sin_family, peerip->sin_port, ((unsigned char*)&peerip->sin_addr.s_addr)[0], ((unsigned char*)&peerip->sin_addr.s_addr)[1], ((unsigned char*)&peerip->sin_addr.s_addr)[2], ((unsigned char*)&peerip->sin_addr.s_addr)[3] ); } else { INFOF("RHIZOME HTTP SERVER, ACCEPT addrlen=%u family=%u data=%s", addr_len, addr.sa_family, alloca_tohex((unsigned char *)addr.sa_data, sizeof addr.sa_data) ); } rhizome_http_request *request = calloc(sizeof(rhizome_http_request), 1); if (request == NULL) { WHYF_perror("calloc(%u, 1)", sizeof(rhizome_http_request)); WHY("Cannot respond to request, out of memory"); } else { /* We are now trying to read the HTTP request */ request->request_type=RHIZOME_HTTP_REQUEST_RECEIVING; request->alarm.function = rhizome_client_poll; connection_stats.name="rhizome_client_poll"; request->alarm.stats=&connection_stats; request->alarm.poll.fd=sock; request->alarm.poll.events=POLLIN; request->alarm.alarm = gettime_ms()+RHIZOME_IDLE_TIMEOUT; request->alarm.deadline = request->alarm.alarm+RHIZOME_IDLE_TIMEOUT; // watch for the incoming http request watch(&request->alarm); // set an inactivity timeout to close the connection schedule(&request->alarm); } } if (errno != EAGAIN) { WARN_perror("accept"); } } if (alarm->poll.revents & (POLLHUP | POLLERR)) { INFO("Error on tcp listen socket"); } }
static ErlDrvData uart_drv_start(ErlDrvPort port, char* command) { (void) command; drv_ctx_t* ctx = NULL; INFOF("memory allocated: %ld", dlib_allocated()); INFOF("total memory allocated: %ld", dlib_total_allocated()); ctx = DZALLOC(sizeof(drv_ctx_t)); dthread_init(&ctx->self, port); if (strncmp(command, "uart_drv", 8) == 0) command += 8; if (*command == ' ') command++; DEBUGF("uart_drv: start (%s)", command); if (strcmp(command, "ftdi") == 0) { #ifdef HAVE_FTDI ctx->other = dthread_start(port, uart_ftdi_main, &ctx->self, 4096); DEBUGF("uart_drv: ftdi thread = %p", ctx->other); #endif } else { #ifdef __WIN32__ if ((*command == '\0') || (strcmp(command, "win32") == 0)) { ctx->other = dthread_start(port, uart_win32_main, &ctx->self, 4096); DEBUGF("uart_drv: win32 thread = %p", ctx->other); } #else if ((*command == '\0') || (strcmp(command, "unix") == 0)) { ctx->other = dthread_start(port, uart_unix_main, &ctx->self, 4096); DEBUGF("uart_drv: unix thread = %p", ctx->other); } #endif } if (ctx->other == NULL) { dthread_finish(&ctx->self); DFREE(ctx); return ERL_DRV_ERROR_BADARG; } dthread_signal_use(&ctx->self, 1); dthread_signal_select(&ctx->self, 1); set_port_control_flags(port, PORT_CONTROL_FLAG_BINARY); return (ErlDrvData) ctx; }
static int open_device(uart_ctx_t* ctx, char* name) { int flags; int fd; #ifdef HAVE_PTY if (strcmp(name, "pty") == 0) { int fd1; char slave_name[UART_MAX_DEVICE_NAME]; if (openpty(&fd,&fd1,slave_name,NULL,NULL) < 0) return -1; INFOF("slave name = %s", slave_name); strcpy(name, slave_name); // close(fd1); // ??? } else #endif { if ((fd = open(name, O_RDWR|O_NDELAY|O_NOCTTY)) < 0) return -1; } flags = fcntl(fd, F_GETFL, 0); fcntl(fd, F_SETFL, flags | O_NONBLOCK); // non-blocking!!! tcflush(fd, TCOFLUSH); tcflush(fd, TCIFLUSH); ctx->fd = fd; DEBUGF("open_device: %d", ctx->fd); return fd; }
static int receive_http_response(int sock, char *buffer, size_t buffer_len, struct http_response_parts *parts) { int len = 0; int count; do { if ((count = read(sock, &buffer[len], buffer_len - len)) == -1) return WHYF_perror("read(%d, %p, %d)", sock, &buffer[len], buffer_len - len); len += count; } while (len < buffer_len && count != 0 && !http_header_complete(buffer, len, len)); if (debug & DEBUG_RHIZOME_RX) DEBUGF("Received HTTP response %s", alloca_toprint(-1, buffer, len)); if (unpack_http_response(buffer, parts) == -1) return -1; if (parts->code != 200 && parts->code != 201) { INFOF("Failed HTTP request: server returned %003u %s", parts->code, parts->reason); return -1; } if (parts->content_length == -1) { if (debug & DEBUG_RHIZOME_RX) DEBUGF("Invalid HTTP reply: missing Content-Length header"); return -1; } DEBUGF("content_length=%d", parts->content_length); return 0; }
DEF_TEST(JpegIdentification, r) { static struct { const char* path; bool isJfif; SkJFIFInfo::Type type; } kTests[] = {{"CMYK.jpg", false, SkJFIFInfo::kGrayscale}, {"color_wheel.jpg", true, SkJFIFInfo::kYCbCr}, {"grayscale.jpg", true, SkJFIFInfo::kGrayscale}, {"mandrill_512_q075.jpg", true, SkJFIFInfo::kYCbCr}, {"randPixels.jpg", true, SkJFIFInfo::kYCbCr}}; for (size_t i = 0; i < SK_ARRAY_COUNT(kTests); ++i) { SkAutoTUnref<SkData> data( load_resource(r, "JpegIdentification", kTests[i].path)); if (!data) { continue; } SkJFIFInfo info; bool isJfif = SkIsJFIF(data, &info); if (isJfif != kTests[i].isJfif) { ERRORF(r, "%s failed isJfif test", kTests[i].path); continue; } if (!isJfif) { continue; // not applicable } if (kTests[i].type != info.fType) { ERRORF(r, "%s failed jfif type test", kTests[i].path); continue; } INFOF(r, "\nJpegIdentification: %s [%d x %d]\n", kTests[i].path, info.fSize.width(), info.fSize.height()); } }
static int dna_helper_harvest(int blocking) { if (dna_helper_pid > 0) { if (blocking && (config.debug.dnahelper)) DEBUGF("DNAHELPER waiting for pid=%d to die", dna_helper_pid); int status; pid_t pid = waitpid(dna_helper_pid, &status, blocking ? 0 : WNOHANG); if (pid == dna_helper_pid) { strbuf b = strbuf_alloca(80); INFOF("DNAHELPER process pid=%u %s", pid, strbuf_str(strbuf_append_exit_status(b, status))); unschedule(&sched_harvester); dna_helper_pid = -1; if (awaiting_reply) { unschedule(&sched_timeout); awaiting_reply = 0; } return 1; } else if (pid == -1) { return WHYF_perror("waitpid(%d, %s)", dna_helper_pid, blocking ? "0" : "WNOHANG"); } else if (pid) { return WHYF("waitpid(%d, %s) returned %d", dna_helper_pid, blocking ? "0" : "WNOHANG", pid); } } return 0; }
FILE *open_logging() { #ifdef ANDROID return NULL; #endif if (!logfile) { const char *logpath = getenv("SERVALD_LOG_FILE"); if (!logpath) { // If the configuration is locked (eg, it called WHY() or DEBUG() while initialising, which // led back to here) then return NULL to indicate the message cannot be logged. if (confLocked()) return NULL; logpath = confValueGet("log.file", NULL); } if (!logpath) { logfile = stderr; INFO("No logfile configured -- logging to stderr"); } else if ((logfile = fopen(logpath, "a"))) { setlinebuf(logfile); INFOF("Logging to %s (fd %d)", logpath, fileno(logfile)); } else { logfile = stderr; WARN_perror("fopen"); WARNF("Cannot append to %s -- falling back to stderr", logpath); } } return logfile; }
/* Open monitor interface abstract domain named socket */ int monitor_client_open(struct monitor_state **res) { int fd; struct sockaddr_un addr; if ( (fd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) { perror("socket"); return -1; } memset(&addr, 0, sizeof(addr)); addr.sun_family = AF_UNIX; int len = monitor_socket_name(&addr); INFOF("Attempting to connect to %s", &addr.sun_path[1]); if (connect(fd, (struct sockaddr*)&addr, len) == -1) { perror("connect"); close(fd); return -1; } *res = (struct monitor_state*)malloc(sizeof(struct monitor_state)); memset(*res,0,sizeof(struct monitor_state)); return fd; }
static void uart_drv_stop(ErlDrvData d) { drv_ctx_t* ctx = (drv_ctx_t*) d; void* value; DEBUGF("uart_drv_stop: called"); dthread_stop(ctx->other, &ctx->self, &value); DEBUGF("uart_drv_stop: signal_use=0"); dthread_signal_use(&ctx->self, 0); DEBUGF("uart_drv_stop: dthread_finish"); dthread_finish(&ctx->self); DFREE(ctx); INFOF("memory allocated: %ld", dlib_allocated()); INFOF("total memory allocated: %ld", dlib_total_allocated()); }
static void test_erasecolor_premul(skiatest::Reporter* reporter, SkColorType ct, SkColor input, SkColor expected) { SkBitmap bm; bm.allocPixels(SkImageInfo::Make(1, 1, ct, kPremul_SkAlphaType)); bm.eraseColor(input); INFOF(reporter, "expected: %x actual: %x\n", expected, bm.getColor(0, 0)); REPORTER_ASSERT(reporter, bm.getColor(0, 0) == expected); }
static SkData* load_resource( skiatest::Reporter* r, const char* test, const char* filename) { SkString path(GetResourcePath(filename)); SkData* data = SkData::NewFromFileName(path.c_str()); if (!data) { INFOF(r, "\n%s: Resource '%s' can not be found.\n", test, filename); } return data; // May return nullptr. }
void set_logging(FILE *f) { logfile = f; if (f == stdout) INFO("Logging to stdout"); else if (f == stderr) INFO("Logging to stderr"); else if (f != NULL) INFOF("Logging to stream with fd=%d", fileno(f)); }
static int load_directory_config() { if (!directory_service && !is_sid_any(config.directory.service.binary)) { directory_service = find_subscriber(config.directory.service.binary, SID_SIZE, 1); if (!directory_service) return WHYF("Failed to create subscriber record"); // used by tests INFOF("ADD DIRECTORY SERVICE %s", alloca_tohex_sid(directory_service->sid)); } // always attempt to reload the address, may depend on DNS resolution return load_subscriber_address(directory_service); }
// send a registration packet static void directory_send(struct subscriber *directory_service, const unsigned char *sid, const char *did, const char *name){ overlay_mdp_frame request; memset(&request, 0, sizeof(overlay_mdp_frame)); request.packetTypeAndFlags = MDP_TX; bcopy(sid, request.out.src.sid, SID_SIZE); request.out.src.port=MDP_PORT_NOREPLY; bcopy(directory_service->sid, request.out.dst.sid, SID_SIZE); request.out.dst.port=MDP_PORT_DIRECTORY; request.out.payload_length = snprintf((char *)request.out.payload, sizeof(request.out.payload), "%s|%s", did, name); // Used by tests INFOF("Sending directory registration for %s, %s, %s to %s", alloca_tohex(sid,7), did, name, alloca_tohex(directory_service->sid, 7)); overlay_mdp_dispatch(&request, 0, NULL, 0); }
// Sanity checks for the GetDateTime function. DEF_TEST(Time_GetDateTime, r) { SkTime::DateTime dateTime; SkTime::GetDateTime(&dateTime); // TODO(future generation): update these values. const uint16_t kMinimumSaneYear = 1964; const uint16_t kMaximumSaneYear = 2064; if (dateTime.fYear < kMinimumSaneYear) { ERRORF(r, "SkTime::GetDateTime: %u (CurrentYear) < %u (MinimumSaneYear)", static_cast<unsigned>(dateTime.fYear), static_cast<unsigned>(kMinimumSaneYear)); } if (dateTime.fYear > kMaximumSaneYear) { ERRORF(r, "SkTime::GetDateTime: %u (CurrentYear) > %u (MaximumSaneYear)", static_cast<unsigned>(dateTime.fYear), static_cast<unsigned>(kMaximumSaneYear)); } REPORTER_ASSERT(r, dateTime.fMonth >= 1); REPORTER_ASSERT(r, dateTime.fMonth <= 12); REPORTER_ASSERT(r, dateTime.fDay >= 1); REPORTER_ASSERT(r, dateTime.fDay <= 31); REPORTER_ASSERT(r, dateTime.fHour <= 23); REPORTER_ASSERT(r, dateTime.fMinute <= 59); REPORTER_ASSERT(r, dateTime.fSecond <= 60); // leap seconds are 23:59:60 // The westernmost timezone is -12:00. // The easternmost timezone is +14:00. REPORTER_ASSERT(r, SkTAbs(SkToInt(dateTime.fTimeZoneMinutes)) <= 14 * 60); SkString timeStamp; dateTime.toISO8601(&timeStamp); REPORTER_ASSERT(r, timeStamp.size() > 0); INFOF(r, "\nCurrent Time (ISO-8601 format): \"%s\"\n", timeStamp.c_str()); }
static int load_directory_config(){ if (!directory_service){ const char *sid_hex = confValueGet("directory.service", NULL); if (!sid_hex) return 0; unsigned char sid[SID_SIZE]; if (stowSid(sid, 0, sid_hex)==-1) return WHYF("Invalid directory server SID %s", sid_hex); directory_service = find_subscriber(sid, SID_SIZE, 1); if (!directory_service) return WHYF("Failed to create subscriber record"); // used by tests INFOF("ADD DIRECTORY SERVICE %s", alloca_tohex_sid(directory_service->sid)); } // always attempt to reload the address, may depend on DNS resolution return load_subscriber_address(directory_service); }
// Initialize thread structure int dthread_init(dthread_t* thr, ErlDrvPort port) { ErlDrvSysInfo sys_info; memset(thr, 0, sizeof(dthread_t)); dthread_signal_init(thr); driver_system_info(&sys_info, sizeof(ErlDrvSysInfo)); // smp_support is used for message passing from thread to // calling process. if SMP is supported the message will go // directly to sender, otherwise it must be sent to port thr->smp_support = sys_info.smp_support; thr->port = port; thr->dport = driver_mk_port(port); thr->owner = driver_connected(port); if (!(thr->iq_mtx = erl_drv_mutex_create("iq_mtx"))) return -1; #ifdef __WIN32__ // create a manual reset event if (!(thr->iq_signal[0] = (ErlDrvEvent) CreateEvent(NULL, TRUE, FALSE, NULL))) { dthread_finish(thr); return -1; } DEBUGF("dthread_init: handle=%d", DTHREAD_EVENT(thr->iq_signal[0])); #else { int pfd[2]; if (pipe(pfd) < 0) { dthread_finish(thr); return -1; } DEBUGF("dthread_init: pipe[0]=%d,pidp[1]=%d", pfd[0], pfd[1]); thr->iq_signal[0] = (ErlDrvEvent) ((long)pfd[0]); thr->iq_signal[1] = (ErlDrvEvent) ((long)pfd[1]); INFOF("pipe: %d,%d", pfd[0], pfd[1]); } #endif return 0; }
int parse_rfd900_rssi(char *s) { int lrssi,rrssi,lnoise,rnoise,rxpackets,temp; // L/R RSSI: 48/0 L/R noise: 62/0 pkts: 0 txe=0 rxe=0 stx=0 srx=0 ecc=0/0 temp=21 dco=0 if (sscanf(s,"L/R RSSI: %d/%d L/R noise: %d/%d pkts: %d txe=%*d rxe=%*d stx=%*d srx=%*d ecc=%*d/%*d temp=%d dco=%*d", &lrssi,&rrssi,&lnoise,&rnoise,&rxpackets, &temp)==6) { int lmargin=(lrssi-lnoise)/1.9; int rmargin=(rrssi-rnoise)/1.9; int maxmargin=lmargin; if (rmargin>maxmargin) maxmargin=rmargin; last_radio_rssi=maxmargin; last_radio_temperature=temp; last_radio_rxpackets=rxpackets; if (gettime_ms()-last_rssi_time>30000) { INFOF("Link budget = %+ddB, temperature=%dC",maxmargin,temp); last_rssi_time=gettime_ms(); } } return 0; }
int overlay_mdp_relevant_bytes(overlay_mdp_frame *mdp) { int len; switch(mdp->packetTypeAndFlags&MDP_TYPE_MASK) { case MDP_ROUTING_TABLE: case MDP_GOODBYE: /* no arguments for saying goodbye */ len=&mdp->raw[0]-(char *)mdp; break; case MDP_ADDRLIST: len=(&mdp->addrlist.sids[0][0]-(unsigned char *)mdp) + mdp->addrlist.frame_sid_count*SID_SIZE; break; case MDP_GETADDRS: len=&mdp->addrlist.sids[0][0]-(unsigned char *)mdp; break; case MDP_TX: len=(&mdp->out.payload[0]-(unsigned char *)mdp) + mdp->out.payload_length; break; case MDP_BIND: len=(&mdp->raw[0] - (char *)mdp) + sizeof(sockaddr_mdp); break; case MDP_SCAN: len=(&mdp->raw[0] - (char *)mdp) + sizeof(struct overlay_mdp_scan); break; case MDP_ERROR: /* This formulation is used so that we don't copy any bytes after the end of the string, to avoid information leaks */ len=(&mdp->error.message[0]-(char *)mdp) + strlen(mdp->error.message)+1; if (mdp->error.error) INFOF("mdp return/error code: %d:%s",mdp->error.error,mdp->error.message); break; default: return WHY("Illegal MDP frame type."); } return len; }
/* Start the Rhizome HTTP server by creating a socket, binding it to an available port, and marking it as passive. If called repeatedly and frequently, this function will only try to start the server after a certain time has elapsed since the last attempt. Return -1 if an error occurs (message logged). Return 0 if the server was started. Return 1 if the server is already started successfully. Return 2 if the server was not started because it is too soon since last failed attempt. */ int rhizome_http_server_start() { if (rhizome_server_socket != -1) return 1; /* Only try to start http server every five seconds. */ time_ms_t now = gettime_ms(); if (now < rhizome_server_last_start_attempt + 5000) return 2; rhizome_server_last_start_attempt = now; if (debug & DEBUG_RHIZOME_TX) DEBUGF("Starting rhizome HTTP server"); unsigned short port; for (port = RHIZOME_HTTP_PORT; port <= RHIZOME_HTTP_PORT_MAX; ++port) { /* Create a new socket, reusable and non-blocking. */ if (rhizome_server_socket == -1) { rhizome_server_socket = socket(AF_INET,SOCK_STREAM,0); if (rhizome_server_socket == -1) { WHY_perror("socket"); goto error; } int on=1; if (setsockopt(rhizome_server_socket, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) == -1) { WHY_perror("setsockopt(REUSEADDR)"); goto error; } if (ioctl(rhizome_server_socket, FIONBIO, (char *)&on) == -1) { WHY_perror("ioctl(FIONBIO)"); goto error; } } /* Bind it to the next port we want to try. */ struct sockaddr_in address; bzero((char *) &address, sizeof(address)); address.sin_family = AF_INET; address.sin_addr.s_addr = INADDR_ANY; address.sin_port = htons(port); if (bind(rhizome_server_socket, (struct sockaddr *) &address, sizeof(address)) == -1) { if (errno != EADDRINUSE) { WHY_perror("bind"); goto error; } } else { /* We bound to a port. The battle is half won. Now we have to successfully listen on that port, which could also fail with EADDRINUSE, in which case we have to scrap the socket and create a new one, because once bound, a socket stays bound. */ if (listen(rhizome_server_socket, 20) != -1) goto success; if (errno != EADDRINUSE) { WHY_perror("listen"); goto error; } close(rhizome_server_socket); rhizome_server_socket = -1; } } WHYF("No ports available in range %u to %u", RHIZOME_HTTP_PORT, RHIZOME_HTTP_PORT_MAX); error: if (rhizome_server_socket != -1) { close(rhizome_server_socket); rhizome_server_socket = -1; } return WHY("Failed to start rhizome HTTP server"); success: INFOF("RHIZOME HTTP SERVER, START port=%d, fd=%d", port, rhizome_server_socket); rhizome_http_server_port = port; /* Add Rhizome HTTPd server to list of file descriptors to watch */ server_alarm.function = rhizome_server_poll; server_stats.name="rhizome_server_poll"; server_alarm.stats=&server_stats; server_alarm.poll.fd = rhizome_server_socket; server_alarm.poll.events = POLLIN; watch(&server_alarm); return 0; }
static int rhizome_server_parse_http_request(rhizome_http_request *r) { /* Switching to writing, so update the call-back */ r->alarm.poll.events=POLLOUT; watch(&r->alarm); // Start building up a response. r->request_type = 0; // Parse the HTTP "GET" line. char *path = NULL; size_t pathlen = 0; if (str_startswith(r->request, "GET ", &path)) { char *p; // This loop is guaranteed to terminate before the end of the buffer, because we know that the // buffer contains at least "\n\n" and maybe "\r\n\r\n" at the end of the header block. for (p = path; !isspace(*p); ++p) ; pathlen = p - path; if ( str_startswith(p, " HTTP/1.", &p) && (str_startswith(p, "0", &p) || str_startswith(p, "1", &p)) && (str_startswith(p, "\r\n", &p) || str_startswith(p, "\n", &p)) ) path[pathlen] = '\0'; else path = NULL; } if (path) { char *id = NULL; INFOF("RHIZOME HTTP SERVER, GET %s", alloca_toprint(1024, path, pathlen)); if (strcmp(path, "/favicon.ico") == 0) { r->request_type = RHIZOME_HTTP_REQUEST_FAVICON; rhizome_server_http_response_header(r, 200, "image/vnd.microsoft.icon", favicon_len); } else if (strcmp(path, "/rhizome/groups") == 0) { /* Return the list of known groups */ rhizome_server_sql_query_http_response(r, "id", "groups", "from groups", 32, 1); } else if (strcmp(path, "/rhizome/files") == 0) { /* Return the list of known files */ rhizome_server_sql_query_http_response(r, "id", "files", "from files", 32, 1); } else if (strcmp(path, "/rhizome/bars") == 0) { /* Return the list of known BARs */ rhizome_server_sql_query_http_response(r, "bar", "manifests", "from manifests", 32, 0); } else if (str_startswith(path, "/rhizome/file/", &id)) { /* Stream the specified payload */ if (!rhizome_str_is_file_hash(id)) { rhizome_server_simple_http_response(r, 400, "<html><h1>Invalid payload ID</h1></html>\r\n"); } else { // TODO: Check for Range: header and return 206 if returning partial content str_toupper_inplace(id); long long rowid = -1; sqlite_exec_int64(&rowid, "select rowid from files where id='%s';", id); if (rowid >= 0 && sqlite3_blob_open(rhizome_db, "main", "files", "data", rowid, 0, &r->blob) != SQLITE_OK) rowid = -1; if (rowid == -1) { rhizome_server_simple_http_response(r, 404, "<html><h1>Payload not found</h1></html>\r\n"); } else { r->source_index = 0; r->blob_end = sqlite3_blob_bytes(r->blob); rhizome_server_http_response_header(r, 200, "application/binary", r->blob_end - r->source_index); r->request_type |= RHIZOME_HTTP_REQUEST_BLOB; } } } else if (str_startswith(path, "/rhizome/manifest/", &id)) { // TODO: Stream the specified manifest rhizome_server_simple_http_response(r, 500, "<html><h1>Not implemented</h1></html>\r\n"); } else { rhizome_server_simple_http_response(r, 404, "<html><h1>Not found</h1></html>\r\n"); } } else { if (debug & DEBUG_RHIZOME_TX) DEBUGF("Received malformed HTTP request: %s", alloca_toprint(120, (const char *)r->request, r->request_length)); rhizome_server_simple_http_response(r, 400, "<html><h1>Malformed request</h1></html>\r\n"); } /* Try sending data immediately. */ rhizome_server_http_send_bytes(r); return 0; }
int monitor_client_read(int fd, struct monitor_state *res, struct monitor_command_handler *handlers, int handler_count) { /* Read any available bytes */ int oldOffset = res->bufferBytes; if (oldOffset+1>=MONITOR_CLIENT_BUFFER_SIZE) return WHY("Buffer full without finding command"); if (res->bufferBytes==0) res->cmd = (char *)res->buffer; int bytesRead=read(fd, res->buffer + oldOffset, MONITOR_CLIENT_BUFFER_SIZE - oldOffset); if (bytesRead<1){ switch(errno) { case ENOTRECOVERABLE: /* transient errors */ WHY_perror("read"); case EINTR: case EAGAIN: #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN case EWOULDBLOCK: #endif return 0; } WHY_perror("read"); return -1; } res->bufferBytes+=bytesRead; again: // wait until we have the whole command line if (res->state == STATE_INIT){ int i; for(i=oldOffset;i<res->bufferBytes;i++){ if (res->buffer[i]=='\n'){ // skip any leading \n's if ((char*)(res->buffer+i) == res->cmd){ res->cmd++; continue; } res->buffer[i]=0; res->dataBytes = 0; res->cmdBytes = i + 1; if (*res->cmd=='*'){ res->cmd++; for (; isdigit(*res->cmd); ++res->cmd) res->dataBytes = res->dataBytes * 10 + *res->cmd - '0'; if (res->dataBytes<0 || res->dataBytes > MONITOR_CLIENT_BUFFER_SIZE) return WHYF("Invalid data length %d", res->dataBytes); if (*res->cmd==':') res->cmd++; } // find all arguments, initialise argc / argv && null terminate strings { char *p=res->cmd; res->argc=0; while (*p && res->argc<MAX_ARGS){ if (*p==':'){ *p=0; res->argv[res->argc]=p+1; res->argc++; } p++; } } if (res->dataBytes){ res->data=(unsigned char *)&res->buffer[i+1]; res->state = STATE_DATA; }else{ res->data=NULL; res->state = STATE_READY; } break; } } } // make sure all the data has arrived if (res->state == STATE_DATA){ if (res->bufferBytes >= res->dataBytes + res->cmdBytes){ res->state = STATE_READY; } } // ok, now we can try to process the command if (res->state == STATE_READY){ int handled=0; int i; // call all handlers that match (yes there might be more than one) for (i=0;i<handler_count;i++){ /* since we know res->cmd is terminated with a '\n', and there shouldn't be a '\n' in h->command, this shouldn't run past the end of the buffer */ if (handlers[i].handler && (!handlers[i].command || strcase_startswith(res->cmd,handlers[i].command, NULL))){ if (handlers[i].handler(res->cmd, res->argc, res->argv, res->data, res->dataBytes, handlers[i].context)>0) handled=1; } } if (!handled){ INFOF("Event \"%s\" was not handled", res->cmd); } // shuffle any unprocessed bytes int remaining = res->bufferBytes - (res->dataBytes + res->cmdBytes); if (remaining>0){ bcopy(res->buffer+res->dataBytes + res->cmdBytes,res->buffer,remaining); } res->bufferBytes=remaining; res->cmdBytes=0; res->dataBytes=0; res->state = STATE_INIT; res->cmd = (char *)res->buffer; oldOffset = 0; goto again; } if (res->bufferBytes >= MONITOR_CLIENT_BUFFER_SIZE) return WHY("Buffer full"); return 0; }
int dna_helper_start() { if (!config.dna.helper.executable[0]) { /* Check if we have a helper configured. If not, then set dna_helper_pid to magic value of 0 so that we don't waste time in future looking up the dna helper configuration value. */ INFO("DNAHELPER none configured"); dna_helper_pid = 0; return 0; } if (!my_subscriber) return WHY("Unable to lookup my SID"); const char *mysid = alloca_tohex_sid_t(my_subscriber->sid); dna_helper_close_pipes(); int stdin_fds[2], stdout_fds[2], stderr_fds[2]; if (pipe(stdin_fds) == -1) return WHY_perror("pipe"); if (pipe(stdout_fds) == -1) { WHY_perror("pipe"); close(stdin_fds[0]); close(stdin_fds[1]); return -1; } if (pipe(stderr_fds) == -1) { WHY_perror("pipe"); close(stdin_fds[0]); close(stdin_fds[1]); close(stdout_fds[0]); close(stdout_fds[1]); return -1; } // Construct argv[] for execv() and log messages. const char *argv[config.dna.helper.argv.ac + 2]; argv[0] = config.dna.helper.executable; unsigned i; for (i = 0; i < config.dna.helper.argv.ac; ++i) argv[i + 1] = config.dna.helper.argv.av[i].value; argv[i + 1] = NULL; strbuf argv_sb = strbuf_append_argv(strbuf_alloca(1024), config.dna.helper.argv.ac + 1, argv); switch (dna_helper_pid = fork()) { case 0: /* Child, should exec() to become helper after installing file descriptors. */ close_log_file(); setenv("MYSID", mysid, 1); signal(SIGTERM, SIG_DFL); close(stdin_fds[1]); close(stdout_fds[0]); close(stderr_fds[0]); if (dup2(stderr_fds[1], 2) == -1 || dup2(stdout_fds[1], 1) == -1 || dup2(stdin_fds[0], 0) == -1) { LOG_perror(LOG_LEVEL_FATAL, "dup2"); _exit(-1); } { execv(config.dna.helper.executable, (char **)argv); LOGF_perror(LOG_LEVEL_FATAL, "execv(%s, [%s])", alloca_str_toprint(config.dna.helper.executable), strbuf_str(argv_sb) ); } do { _exit(-1); } while (1); break; case -1: /* fork failed */ WHY_perror("fork"); close(stdin_fds[0]); close(stdin_fds[1]); close(stdout_fds[0]); close(stdout_fds[1]); close(stderr_fds[0]); close(stderr_fds[1]); return -1; default: /* Parent, should put file descriptors into place for use */ close(stdin_fds[0]); close(stdout_fds[1]); close(stderr_fds[1]); dna_helper_started = 0; dna_helper_stdin = stdin_fds[1]; dna_helper_stdout = stdout_fds[0]; dna_helper_stderr = stderr_fds[0]; INFOF("STARTED DNA HELPER pid=%u stdin=%d stdout=%d stderr=%d executable=%s argv=[%s]", dna_helper_pid, dna_helper_stdin, dna_helper_stdout, dna_helper_stderr, alloca_str_toprint(config.dna.helper.executable), strbuf_str(argv_sb) ); sched_replies.poll.fd = dna_helper_stdout; sched_replies.poll.events = POLLIN; sched_errors.poll.fd = dna_helper_stderr; sched_errors.poll.events = POLLIN; sched_requests.poll.fd = -1; sched_requests.poll.events = POLLOUT; sched_harvester.alarm = gettime_ms() + 1000; sched_harvester.deadline = sched_harvester.alarm + 1000; reply_bufend = reply_buffer; discarding_until_nl = 0; awaiting_reply = 0; watch(&sched_replies); watch(&sched_errors); schedule(&sched_harvester); return 0; } return -1; }
// thread main! int uart_unix_main(void* arg) { dthread_t* self = (dthread_t*) arg; dthread_t* other = (dthread_t*) self->arg; dmessage_t* mp = NULL; dthread_poll_event_t ev, *evp; size_t nev; dterm_t term; uart_ctx_t ctx; ErlDrvTermData mp_from; ErlDrvTermData mp_ref; dthread_t* mp_source; int tmo; int r; DEBUGF("uart_unix: thread started"); uart_init(&ctx, self, other); dterm_init(&term); again_tmo: tmo = next_timeout(&ctx); again: nev = 0; evp = NULL; if (ctx.fd >= 0) { ev.event = (ErlDrvEvent) ((long)ctx.fd); ev.events = 0; if ((ctx.option.active != UART_PASSIVE) || ctx.recv) { ev.events |= ERL_DRV_READ; if (ctx.option.ptypkt && (ctx.fd != ctx.tty_fd)) ev.events |= ERL_DRV_EXCEP; } if (ctx.oq.mesg) ev.events |= ERL_DRV_WRITE; if (ev.events) { evp = &ev; nev = 1; } DEBUGF("ctx.fd=%d, ev.events=%d", ctx.fd, ev.events); } DEBUGF("uart_unix_main: nev=%d, events=%x, timeout = %d", nev, ev.events, tmo); r = dthread_poll(self, evp, &nev, tmo); if (r < 0) { DEBUGF("uart_unix_main: dthread_poll failed=%d", r); goto again_tmo; } else { DEBUGF("uart_unix_main: nev=%d, r=%d", nev, r); if (evp && (nev == 1)) { if (evp->revents & ERL_DRV_WRITE) process_output(&ctx, self); if (evp->revents & (ERL_DRV_READ|ERL_DRV_EXCEP)) { while((process_input(&ctx, self, 0) == 1) && (ctx.option.active != UART_PASSIVE)) ; } } tmo = next_timeout(&ctx); DEBUGF("uart_unix_main: timeout = %d", tmo); if (ctx.recv) { if (tmo == 0) { uart_async_error_am(&ctx, ctx.dport, ctx.caller, am_timeout); clear_timeout(&ctx); ctx.remain = 0; } } if (r == 0) goto again; // r>0 (number of messages) DEBUGF("about to receive message r=%d", r); if ((mp = dthread_recv(self, NULL)) == NULL) { DEBUGF("uart_unix_main: message was NULL"); goto again; } mp_from = mp->from; mp_ref = mp->ref; mp_source = mp->source; switch (mp->cmd) { case DTHREAD_STOP: DEBUGF("uart_unix_main: STOP"); close_device(&ctx); uart_final(&ctx); dmessage_free(mp); DEBUGF("uart_unix_main: EXIT"); dthread_exit(0); break; case DTHREAD_OUTPUT: // async send! DEBUGF("uart_unix_main: OUTPUT"); if (ctx.fd < 0) { dmessage_free(mp); goto again; } if (enq_output(&ctx, self, mp, 0) < 0) { mp = NULL; goto error; } goto again; case UART_CMD_CONNECT: { ErlDrvTermData owner; if (mp->used != 0) goto badarg; owner = driver_connected(self->port); self->owner = owner; other->owner = owner; goto ok; } case UART_CMD_CLOSE: DEBUGF("uart_unix_main: CLOSE"); close_device(&ctx); goto ok; case UART_CMD_SEND: // sync send DEBUGF("uart_unix_main: SEND"); if (ctx.fd < 0) goto ebadf; if (enq_output(&ctx, self, mp, mp_from) < 0) { mp = NULL; goto error; } goto again; case UART_CMD_SENDCHAR: // sync send DEBUGF("uart_unix_main: SENDCHAR"); if (ctx.fd < 0) goto ebadf; if (enq_output(&ctx, self, mp, mp_from) < 0) { mp = NULL; goto error; } goto again; case UART_CMD_RECV: { // <<Time:32, Length:32>> Time=0xffffffff=inf uint32_t tm; int len; DEBUGF("uart_unix_main: RECV"); if (ctx.fd < 0) goto ebadf; if (ctx.recv) goto ealready; if (mp->used != 8) goto badarg; if (ctx.option.active != UART_PASSIVE) goto badarg; tm = get_uint32((uint8_t*) mp->buffer); len = (int) get_uint32((uint8_t*) (mp->buffer+4)); if ((len < 0) || (len > UART_MAX_PACKET_SIZE)) goto badarg; ctx.ref = mp_ref; ctx.caller = mp_from; set_timeout(&ctx, tm); ctx.recv = 1; DEBUGF("recv timeout %lu", tm); process_input(&ctx, self, len); dmessage_free(mp); goto again_tmo; } case UART_CMD_UNRECV: { // argument is data to push back uart_buf_push(&ctx.ib, mp->buffer, mp->used); DEBUGF("unrecived %d bytes", ctx.ib.ptr - ctx.ib.ptr_start); if (ctx.option.active != UART_PASSIVE) { while((process_input(&ctx, self, 0) == 1) && (ctx.option.active != UART_PASSIVE)) ; } goto ok; } case UART_CMD_SETOPTS: { uart_com_state_t state = ctx.state; uart_opt_t option = ctx.option; uint32_t sflags = ctx.sflags; // parse & update options in state,option and sflag if (uart_parse_opts(mp->buffer, mp->used, &state, &option, &sflags) < 0) goto badarg; // apply the changed values if ((r=apply_opts(&ctx, &state, &option, sflags)) < 0) goto error; if (r == 1) { while((process_input(&ctx, self, 0) == 1) && (ctx.option.active != UART_PASSIVE)) ; } goto ok; } case UART_CMD_GETOPTS: { dterm_mark_t m1; dterm_mark_t m2; // {Ref, {ok,List}} || {Ref, {error,Reason}} dterm_tuple_begin(&term, &m1); { dterm_uint(&term, mp_ref); dterm_tuple_begin(&term, &m2); { dterm_atom(&term, am_ok); if (uart_get_opts(&term, &ctx,(uint8_t*)mp->buffer,mp->used) < 0) { dterm_reset(&term); goto badarg; } } dterm_tuple_end(&term, &m2); } dterm_tuple_end(&term, &m1); dthread_port_send_dterm(mp_source, self, mp_from, &term); dterm_reset(&term); dmessage_free(mp); goto again; } case UART_CMD_GET_MODEM: { dterm_mark_t m1; dterm_mark_t m2; uart_modem_state_t mstate; if (ctx.tty_fd < 0) goto ebadf; if (get_modem_state(ctx.tty_fd, &mstate) < 0) goto error; dterm_tuple_begin(&term, &m1); { dterm_uint(&term, mp_ref); dterm_tuple_begin(&term, &m2); { dterm_atom(&term, am_ok); modem_state_dterm(&term, mstate); } dterm_tuple_end(&term, &m2); } dterm_tuple_end(&term, &m1); dthread_port_send_dterm(mp_source, self, mp_from, &term); dterm_reset(&term); dmessage_free(mp); goto again; } case UART_CMD_SET_MODEM: { uart_modem_state_t mstate; if (ctx.tty_fd < 0) goto ebadf; if (mp->used != 4) goto badarg; mstate = (uart_modem_state_t) get_uint32((uint8_t*) mp->buffer); if (set_modem_state(ctx.tty_fd, mstate, 1) < 0) goto error; goto ok; } case UART_CMD_CLR_MODEM: { uart_modem_state_t mstate; if (ctx.tty_fd < 0) goto ebadf; if (mp->used != 4) goto badarg; mstate = (uart_modem_state_t) get_uint32((uint8_t*) mp->buffer); if (set_modem_state(ctx.tty_fd, mstate, 0) < 0) goto error; goto ok; } case UART_CMD_HANGUP: { struct termios tio; int r; if (ctx.tty_fd < 0) goto ebadf; if (mp->used != 0) goto badarg; if ((r = tcgetattr(ctx.tty_fd, &tio)) < 0) { INFOF("tcgetattr: error=%s\n", strerror(errno)); goto badarg; } cfsetispeed(&tio, B0); cfsetospeed(&tio, B0); if ((r = tcsetattr(ctx.tty_fd, TCSANOW, &tio)) < 0) { INFOF("tcsetattr: error=%s\n", strerror(errno)); goto badarg; } goto ok; } case UART_CMD_BREAK: { int duration; if (ctx.tty_fd < 0) goto ebadf; if (mp->used != 4) goto badarg; duration = (int) get_uint32((uint8_t*) mp->buffer); if (tcsendbreak(ctx.tty_fd, duration) < 0) goto error; goto ok; } case UART_CMD_FLOW: if (ctx.tty_fd < 0) goto ebadf; if (mp->used != 1) goto badarg; switch(mp->buffer[0]) { case 0: r = tcflow(ctx.tty_fd, TCIOFF); break; case 1: r = tcflow(ctx.tty_fd, TCION); break; case 2: r = tcflow(ctx.tty_fd, TCOOFF); break; case 3: r = tcflow(ctx.tty_fd, TCOON); break; default: goto badarg; break; } if (r < 0) goto error; goto ok; default: goto badarg; } } ok: dthread_port_send_ok(mp_source, self, mp_from, mp_ref); if (mp) dmessage_free(mp); goto again; ebadf: errno = EBADF; goto error; badarg: errno = EINVAL; goto error; ealready: errno = EALREADY; goto error; error: dthread_port_send_error(mp_source, self, mp_from, mp_ref, uart_errno(&ctx)); if (mp) dmessage_free(mp); goto again; }
int overlay_saw_mdp_frame(overlay_mdp_frame *mdp, time_ms_t now) { IN(); int i; int match=-1; switch(mdp->packetTypeAndFlags&MDP_TYPE_MASK) { case MDP_TX: /* Regular MDP frame addressed to us. Look for matching port binding, and if available, push to client. Else do nothing, or if we feel nice send back a connection refused type message? Silence is probably the more prudent path. */ if (debug & DEBUG_MDPREQUESTS) DEBUGF("Received packet with listener (MDP ports: src=%s*:%d, dst=%d)", alloca_tohex(mdp->out.src.sid, 7), mdp->out.src.port,mdp->out.dst.port); // TODO pass in dest subscriber as an argument, we should know it by now struct subscriber *destination = NULL; if (!is_broadcast(mdp->out.dst.sid)){ destination = find_subscriber(mdp->out.dst.sid, SID_SIZE, 1); } for(i=0;i<MDP_MAX_BINDINGS;i++) { if (mdp_bindings[i].port!=mdp->out.dst.port) continue; if ((!destination) || mdp_bindings[i].subscriber == destination){ /* exact match, so stop searching */ match=i; break; }else if (!mdp_bindings[i].subscriber){ /* If we find an "ANY" binding, remember it. But we will prefer an exact match if we find one */ match=i; } } if (match>-1) { struct sockaddr_un addr; bcopy(mdp_bindings[match].socket_name,addr.sun_path,mdp_bindings[match].name_len); addr.sun_family=AF_UNIX; errno=0; int len=overlay_mdp_relevant_bytes(mdp); int r=sendto(mdp_named.poll.fd,mdp,len,0,(struct sockaddr*)&addr,sizeof(addr)); if (r==overlay_mdp_relevant_bytes(mdp)) { RETURN(0); } WHY("didn't send mdp packet"); if (errno==ENOENT) { /* far-end of socket has died, so drop binding */ INFOF("Closing dead MDP client '%s'",mdp_bindings[match].socket_name); overlay_mdp_releasebindings(&addr,mdp_bindings[match].name_len); } WHY_perror("sendto(e)"); RETURN(WHY("Failed to pass received MDP frame to client")); } else { /* No socket is bound, ignore the packet ... except for magic sockets */ switch(mdp->out.dst.port) { case MDP_PORT_VOMP: RETURN(vomp_mdp_received(mdp)); case MDP_PORT_KEYMAPREQUEST: /* Either respond with the appropriate SAS, or record this one if it verifies out okay. */ if (debug & DEBUG_MDPREQUESTS) DEBUG("MDP_PORT_KEYMAPREQUEST"); RETURN(keyring_mapping_request(keyring,mdp)); case MDP_PORT_DNALOOKUP: /* attempt to resolve DID to SID */ { int cn=0,in=0,kp=0; char did[64+1]; int pll=mdp->out.payload_length; if (pll>64) pll=64; /* get did from the packet */ if (mdp->out.payload_length<1) { RETURN(WHY("Empty DID in DNA resolution request")); } bcopy(&mdp->out.payload[0],&did[0],pll); did[pll]=0; if (debug & DEBUG_MDPREQUESTS) DEBUG("MDP_PORT_DNALOOKUP"); int results=0; while(keyring_find_did(keyring,&cn,&in,&kp,did)) { /* package DID and Name into reply (we include the DID because it could be a wild-card DID search, but the SID is implied in the source address of our reply). */ if (keyring->contexts[cn]->identities[in]->keypairs[kp]->private_key_len > DID_MAXSIZE) /* skip excessively long DID records */ continue; const unsigned char *packedSid = keyring->contexts[cn]->identities[in]->keypairs[0]->public_key; const char *unpackedDid = (const char *) keyring->contexts[cn]->identities[in]->keypairs[kp]->private_key; const char *name = (const char *)keyring->contexts[cn]->identities[in]->keypairs[kp]->public_key; // URI is sid://SIDHEX/DID strbuf b = strbuf_alloca(SID_STRLEN + DID_MAXSIZE + 10); strbuf_puts(b, "sid://"); strbuf_tohex(b, packedSid, SID_SIZE); strbuf_puts(b, "/local/"); strbuf_puts(b, unpackedDid); overlay_mdp_dnalookup_reply(&mdp->out.src, packedSid, strbuf_str(b), unpackedDid, name); kp++; results++; } if (!results) { /* No local results, so see if servald has been configured to use a DNA-helper that can provide additional mappings. This provides a generalised interface for resolving telephone numbers into URIs. The first use will be for resolving DIDs to SIP addresses for OpenBTS boxes run by the OTI/Commotion project. The helper is run asynchronously, and the replies will be delivered when results become available, so this function will return immediately, so as not to cause blockages and delays in servald. */ dna_helper_enqueue(mdp, did, mdp->out.src.sid); monitor_tell_formatted(MONITOR_DNAHELPER, "LOOKUP:%s:%d:%s\n", alloca_tohex_sid(mdp->out.src.sid), mdp->out.src.port, did); } RETURN(0); } break; case MDP_PORT_ECHO: /* well known ECHO port for TCP/UDP and now MDP */ { /* Echo is easy: we swap the sender and receiver addresses (and thus port numbers) and send the frame back. */ /* Swap addresses */ overlay_mdp_swap_src_dst(mdp); /* Prevent echo:echo connections and the resulting denial of service from triggering endless pongs. */ if (mdp->out.dst.port==MDP_PORT_ECHO) { RETURN(WHY("echo loop averted")); } /* If the packet was sent to broadcast, then replace broadcast address with our local address. For now just responds with first local address */ if (is_broadcast(mdp->out.src.sid)) { if (my_subscriber) bcopy(my_subscriber->sid, mdp->out.src.sid,SID_SIZE); else /* No local addresses, so put all zeroes */ bzero(mdp->out.src.sid,SID_SIZE); } /* queue frame for delivery */ overlay_mdp_dispatch(mdp,0 /* system generated */, NULL,0); /* and switch addresses back around in case the caller was planning on using MDP structure again (this happens if there is a loop-back reply and the frame needs sending on, as happens with broadcasts. MDP ping is a simple application where this occurs). */ overlay_mdp_swap_src_dst(mdp); } break; default: /* Unbound socket. We won't be sending ICMP style connection refused messages, partly because they are a waste of bandwidth. */ RETURN(WHYF("Received packet for which no listening process exists (MDP ports: src=%d, dst=%d", mdp->out.src.port,mdp->out.dst.port)); } } break; default: RETURN(WHYF("We should only see MDP_TX frames here (MDP message type = 0x%x)", mdp->packetTypeAndFlags)); } RETURN(0); }
extern void dthread_event_close(ErlDrvEvent event) { INFOF("event_close: %d", DTHREAD_EVENT(event)); DTHREAD_CLOSE_EVENT(event); }
static int overlay_saw_mdp_frame(struct overlay_frame *frame, overlay_mdp_frame *mdp, time_ms_t now) { IN(); int i; int match=-1; switch(mdp->packetTypeAndFlags&MDP_TYPE_MASK) { case MDP_TX: /* Regular MDP frame addressed to us. Look for matching port binding, and if available, push to client. Else do nothing, or if we feel nice send back a connection refused type message? Silence is probably the more prudent path. */ if (config.debug.mdprequests) DEBUGF("Received packet with listener (MDP ports: src=%s*:%d, dst=%d)", alloca_tohex(mdp->out.src.sid, 7), mdp->out.src.port,mdp->out.dst.port); // TODO pass in dest subscriber as an argument, we should know it by now struct subscriber *destination = NULL; if (frame) destination = frame->destination; else if (!is_sid_broadcast(mdp->out.dst.sid)){ destination = find_subscriber(mdp->out.dst.sid, SID_SIZE, 1); } for(i=0;i<MDP_MAX_BINDINGS;i++) { if (mdp_bindings[i].port!=mdp->out.dst.port) continue; if ((!destination) || mdp_bindings[i].subscriber == destination){ /* exact match, so stop searching */ match=i; break; }else if (!mdp_bindings[i].subscriber){ /* If we find an "ANY" binding, remember it. But we will prefer an exact match if we find one */ match=i; } } if (match>-1) { struct sockaddr_un addr; bcopy(mdp_bindings[match].socket_name,addr.sun_path,mdp_bindings[match].name_len); addr.sun_family=AF_UNIX; errno=0; int len=overlay_mdp_relevant_bytes(mdp); int r=sendto(mdp_named.poll.fd,mdp,len,0,(struct sockaddr*)&addr,sizeof(addr)); if (r==overlay_mdp_relevant_bytes(mdp)) { RETURN(0); } WHY("didn't send mdp packet"); if (errno==ENOENT) { /* far-end of socket has died, so drop binding */ INFOF("Closing dead MDP client '%s'",mdp_bindings[match].socket_name); overlay_mdp_releasebindings(&addr,mdp_bindings[match].name_len); } WHY_perror("sendto(e)"); RETURN(WHY("Failed to pass received MDP frame to client")); } else { /* No socket is bound, ignore the packet ... except for magic sockets */ RETURN(overlay_mdp_try_interal_services(frame, mdp)); } break; default: RETURN(WHYF("We should only see MDP_TX frames here (MDP message type = 0x%x)", mdp->packetTypeAndFlags)); } RETURN(0); OUT(); }
static void codec_yuv(skiatest::Reporter* reporter, const char path[], SkISize expectedSizes[3]) { SkAutoTDelete<SkStream> stream(resource(path)); if (!stream) { INFOF(reporter, "Missing resource '%s'\n", path); return; } SkAutoTDelete<SkCodec> codec(SkCodec::NewFromStream(stream.detach())); REPORTER_ASSERT(reporter, codec); if (!codec) { return; } // Test queryYUV8() SkYUVSizeInfo info; bool success = codec->queryYUV8(nullptr, nullptr); REPORTER_ASSERT(reporter, !success); success = codec->queryYUV8(&info, nullptr); REPORTER_ASSERT(reporter, (expectedSizes == nullptr) == !success); if (!success) { return; } REPORTER_ASSERT(reporter, 0 == memcmp((const void*) &info, (const void*) expectedSizes, 3 * sizeof(SkISize))); REPORTER_ASSERT(reporter, info.fWidthBytes[SkYUVSizeInfo::kY] == (uint32_t) SkAlign8(info.fSizes[SkYUVSizeInfo::kY].width())); REPORTER_ASSERT(reporter, info.fWidthBytes[SkYUVSizeInfo::kU] == (uint32_t) SkAlign8(info.fSizes[SkYUVSizeInfo::kU].width())); REPORTER_ASSERT(reporter, info.fWidthBytes[SkYUVSizeInfo::kV] == (uint32_t) SkAlign8(info.fSizes[SkYUVSizeInfo::kV].width())); SkYUVColorSpace colorSpace; success = codec->queryYUV8(&info, &colorSpace); REPORTER_ASSERT(reporter, 0 == memcmp((const void*) &info, (const void*) expectedSizes, 3 * sizeof(SkISize))); REPORTER_ASSERT(reporter, info.fWidthBytes[SkYUVSizeInfo::kY] == (uint32_t) SkAlign8(info.fSizes[SkYUVSizeInfo::kY].width())); REPORTER_ASSERT(reporter, info.fWidthBytes[SkYUVSizeInfo::kU] == (uint32_t) SkAlign8(info.fSizes[SkYUVSizeInfo::kU].width())); REPORTER_ASSERT(reporter, info.fWidthBytes[SkYUVSizeInfo::kV] == (uint32_t) SkAlign8(info.fSizes[SkYUVSizeInfo::kV].width())); REPORTER_ASSERT(reporter, kJPEG_SkYUVColorSpace == colorSpace); // Allocate the memory for the YUV decode size_t totalBytes = info.fWidthBytes[SkYUVSizeInfo::kY] * info.fSizes[SkYUVSizeInfo::kY].height() + info.fWidthBytes[SkYUVSizeInfo::kU] * info.fSizes[SkYUVSizeInfo::kU].height() + info.fWidthBytes[SkYUVSizeInfo::kV] * info.fSizes[SkYUVSizeInfo::kV].height(); SkAutoMalloc storage(totalBytes); void* planes[3]; planes[0] = storage.get(); planes[1] = SkTAddOffset<void>(planes[0], info.fWidthBytes[SkYUVSizeInfo::kY] * info.fSizes[SkYUVSizeInfo::kY].height()); planes[2] = SkTAddOffset<void>(planes[1], info.fWidthBytes[SkYUVSizeInfo::kU] * info.fSizes[SkYUVSizeInfo::kU].height()); // Test getYUV8Planes() REPORTER_ASSERT(reporter, SkCodec::kInvalidInput == codec->getYUV8Planes(info, nullptr)); REPORTER_ASSERT(reporter, SkCodec::kSuccess == codec->getYUV8Planes(info, planes)); }