void ErrorToClient(struct handlerdata *hd, struct client_msg * cm ) { cm->payload = 0 ; cm->size = 0 ; cm->offset = 0 ; ToClient(hd->file_descriptor, cm, NULL); // send the ping }
void PingClient(struct handlerdata *hd) { ToClient(hd->file_descriptor, &ping_cm, NULL); // send the ping }
void RulerCtrl::Paint(Draw& draw) { Size client = GetSize(); int csize = is_vert ? client.cy : client.cx; int cheight = is_vert ? client.cx : client.cy; Rect clip = GetSize(); int cy = font.Info().GetHeight(); double pos1 = FromClient(0); double pos2 = FromClient(csize); if(pos1 > pos2) Swap(pos1, pos2); double lrange = min_range, rrange = max_range; if(!IsNull(min_range) && pos1 < min_range) pos1 = min_range; if(!IsNull(max_range) && pos2 > max_range) pos2 = max_range; int cli1 = 0, cli2 = csize; if(scale < 0) Swap(lrange, rrange); if(!IsNull(lrange)) cli1 = max<int>(cli1, ToClient(lrange)); if(!IsNull(rrange)) cli2 = min<int>(cli2, ToClient(rrange)); Rect nclip; if(is_vert) { draw.DrawRect(0, 0, client.cx, cli1, outer_color); if(!IsNull(lrange)) draw.DrawRect(0, cli1++, client.cx, 1, SBlack); draw.DrawRect(0, cli2, client.cx, client.cy - cli2, outer_color); if(!IsNull(rrange)) draw.DrawRect(0, --cli2, client.cx, 1, SBlack); draw.DrawRect(0, cli1, 1, cli2 - cli1, SGray); // draw.DrawRect(0, cli1, 1, cli2 - cli1, SBlack); draw.DrawRect(client.cx - 1, cli1, 1, cli2 - cli1, SBlack); nclip = RectC(1, cli1, client.cx - 2, cli2 - cli1); } else { draw.DrawRect(0, 0, cli1, client.cy, outer_color); if(!IsNull(lrange)) draw.DrawRect(cli1++, 0, 1, client.cy, SBlack); draw.DrawRect(cli2, 0, client.cx - cli2, client.cy, outer_color); if(!IsNull(rrange)) draw.DrawRect(--cli2, 0, 1, client.cy, SBlack); draw.DrawRect(cli1, 0, cli2 - cli1, 1, SGray); draw.DrawRect(cli1, client.cy - 1, cli2 - cli1, 1, SBlack); nclip = RectC(cli1, 1, cli2 - cli1, client.cy - 2); } draw.DrawRect(nclip, background); draw.Clip(nclip); enum { SMALL_LIMIT = 100, // TEXT_LIMIT = 50, TGAP = 3, HGAP = 2, VGAP = 0, HXGAP = 3, VXGAP = 2, SMALL_SIZE = 5, }; double rep_count = 1; double rep_delta = 0; if(!IsNull(small_repeat)) { rep_delta = small_repeat * floor(pos1 / small_repeat); rep_count = ceil(pos2 / small_repeat) - floor(pos1 / small_repeat); } if(!small_step.IsEmpty() && rep_count > 0 && rep_count * small_step.GetCount() <= cli2 - cli1) { int ix = BinFindIndex(small_step, pos1 - rep_delta); int ppos = (is_right ? 0 : cheight - SMALL_SIZE); for(int c = fround(rep_count); --c >= 0; ix = 0, rep_delta += small_repeat) { int lim = small_step.GetCount(); if(small_step.Top() > pos2 - rep_delta) lim = BinFindIndex(small_step, pos2 - rep_delta); for(; ix < lim; ix++) { int cli = ToClient(small_step[ix] + rep_delta); if(is_vert) draw.DrawRect(ppos, cli, SMALL_SIZE, 1, Gray()); else draw.DrawRect(cli, ppos, 1, SMALL_SIZE, Gray()); } } } rep_count = 1; double rep_index = 0; if(!IsNull(text_repeat)) { rep_index = floor(pos1 / text_repeat); rep_count = ceil(pos2 / text_repeat) - floor(pos1 / text_repeat) + 1; } if(!text_step.IsEmpty() && (!text_value.IsEmpty() || text_convert) && rep_count > 0 /*&& rep_count * text_step.GetCount() <= TEXT_LIMIT*/) { int ix = BinFindIndex(text_step, pos1 - rep_index * text_repeat); int ppos = (is_right ? SMALL_SIZE : cheight - cy - SMALL_SIZE); int rpos = (is_right ? 0 : cheight - SMALL_SIZE - 1); for(int c = fround(rep_count); --c >= 0; ix = 0, rep_index++) { int lim = text_step.GetCount(); double dp2 = pos2 - rep_index * text_repeat; if(text_step.Top() > dp2) { lim = BinFindIndex(text_step, dp2); if(lim + 1 < text_step.GetCount() && text_step[lim + 1] - dp2 < dp2 - text_step[lim]) lim++; } for(; ix < lim; ix++) { double value = text_step[ix] + rep_index * text_repeat; int cli = ToClient(value); String text; if(ix < text_value.GetCount()) text = text_value[ix]; else if(text_convert) text = StdFormat(text_convert -> Format(value)); else text = StdFormat(value); Size tsize = GetTextSize(text, font); int half = tsize.cx >> 1; if(is_vert) { draw.DrawRect(0, cli, ppos, 1, Black()); draw.DrawRect(rpos, cli, SMALL_SIZE + 1, 1, Black()); // draw.DrawRect(ppos - VGAP, cli - half - HGAP, tsize.cy + 2 * VGAP, tsize.cx + 2 * HGAP, background); draw.DrawText(ppos, cli + half, 900, text, font, Gray()); } else { draw.DrawRect(cli, 0, 1, ppos, Black()); draw.DrawRect(cli, rpos, 1, SMALL_SIZE + 1, Black()); // draw.DrawRect(cli - half - HGAP, ppos - VGAP, tsize.cx + 2 * HGAP, tsize.cy + 2 * VGAP, background); draw.DrawText(cli - half, ppos, text, font, Gray()); } } } }
/* * lower level routine for actually handling a request * deals with data (ping is handled higher) */ void *DataHandler(void *v) { struct handlerdata *hd = v; char *retbuffer = NULL; struct client_msg cm; // the return message #if OW_CYGWIN /* Random generator seem to need initialization for each new thread * If not, seed will be reset and rand() will return 0 the first call. */ { struct timeval tv; gettimeofday(&tv, NULL); srand((unsigned int) tv.tv_usec); } #endif memset(&cm, 0, sizeof(struct client_msg)); cm.version = MakeServerprotocol(OWSERVER_PROTOCOL_VERSION); cm.control_flags = hd->sm.control_flags; // default flag return -- includes persistence state /* Pre-handling for special testing mode to exclude certain messages */ switch ((enum msg_classification) hd->sm.type) { case msg_dirall: case msg_dirallslash: if (Globals.no_dirall) { LEVEL_DEBUG("DIRALL message rejected.") ; hd->sm.type = msg_error; } break; case msg_get: case msg_getslash: if (Globals.no_get) { LEVEL_DEBUG("GET message rejected.") ; hd->sm.type = msg_error; } break; default: break; } /* Now Check message types and only parse valid messages */ switch ((enum msg_classification) hd->sm.type) { // outer switch case msg_read: // good message case msg_write: // good message case msg_dir: // good message case msg_presence: // good message case msg_dirall: // good message case msg_dirallslash: // good message case msg_get: // good message case msg_getslash: // good message if (hd->sm.payload == 0) { /* Bad query -- no data after header */ LEVEL_DEBUG("No payload -- ignore.") ; cm.ret = -EBADMSG; } else { struct parsedname *pn; OWQ_allocate_struct_and_pointer(owq); pn = PN(owq); /* Parse the path string and crete query object */ LEVEL_CALL("DataHandler: parse path=%s", hd->sp.path); cm.ret = BAD( OWQ_create(hd->sp.path, owq) ) ? -1 : 0 ; if ( cm.ret != 0 ) { LEVEL_DEBUG("DataHandler: OWQ_create failed cm.ret=%d", cm.ret); break; } /* Use client persistent settings (temp scale, display mode ...) */ pn->control_flags = hd->sm.control_flags; /* Override some settings from control flags */ if ( (pn->control_flags & UNCACHED) != 0 ) { // client wants uncached pn->state |= ePS_uncached; } if ( (pn->control_flags & ALIAS_REQUEST) == 0 ) { // client wants unaliased pn->state |= ePS_unaliased; } /* Antilooping tags */ pn->tokens = hd->sp.tokens; pn->tokenstring = hd->sp.tokenstring; //printf("Handler: sm.sg=%X pn.state=%X\n", sm.sg, pn.state); //printf("Scale=%s\n", TemperatureScaleName(SGTemperatureScale(sm.sg))); switch ((enum msg_classification) hd->sm.type) { case msg_presence: LEVEL_CALL("Presence message for %s", SAFESTRING(pn->path)); // Basically, if we were able to ParsedName it's here! cm.size = 0; retbuffer = owmalloc( SERIAL_NUMBER_SIZE ) ; if ( retbuffer ) { memcpy( retbuffer, pn->sn, SERIAL_NUMBER_SIZE ) ; cm.payload = SERIAL_NUMBER_SIZE ; } else { cm.payload = 0 ; } cm.ret = 0; // good answer break; case msg_read: LEVEL_CALL("Read message"); retbuffer = ReadHandler(hd, &cm, owq); LEVEL_DEBUG("Read message done value=%p", retbuffer); break; case msg_write: LEVEL_CALL("Write message"); if ( (int) hd->sp.datasize < hd->sm.size ) { cm.ret = -EMSGSIZE; } else { /* set buffer (size already set) */ OWQ_assign_write_buffer( (ASCII *) hd->sp.data, hd->sm.size, hd->sm.offset, owq) ; WriteHandler(hd, &cm, owq); } break; case msg_dir: LEVEL_CALL("Directory message (one at a time)"); DirHandler(hd, &cm, pn); break; case msg_dirall: LEVEL_CALL("Directory message (all at once)"); retbuffer = DirallHandler(hd, &cm, pn); break; case msg_dirallslash: LEVEL_CALL("Directory message (all at once, with directory /)"); retbuffer = DirallslashHandler(hd, &cm, pn); break; case msg_get: if (IsDir(pn)) { LEVEL_CALL("Get -> Directory message (all at once)"); retbuffer = DirallHandler(hd, &cm, pn); } else { LEVEL_CALL("Get -> Read message"); retbuffer = ReadHandler(hd, &cm, owq); } break; case msg_getslash: if (IsDir(pn)) { LEVEL_CALL("Get -> Directory message (all at once)"); retbuffer = DirallslashHandler(hd, &cm, pn); } else { LEVEL_CALL("Get -> Read message"); retbuffer = ReadHandler(hd, &cm, owq); } break; default: // never reached LEVEL_CALL("Error: unknown message %d", (int) hd->sm.type); break; } OWQ_destroy(owq); LEVEL_DEBUG("DataHandler: FS_ParsedName_destroy done"); } break; case msg_nop: // "bad" message LEVEL_CALL("NOP message"); cm.ret = 0; break; case msg_size: // no longer used case msg_error: default: // "bad" message cm.ret = -ENOMSG; LEVEL_CALL("No message"); break; } LEVEL_DEBUG("DataHandler: cm.ret=%d", cm.ret); TOCLIENTLOCK(hd); if (cm.ret != -EIO) { ToClient(hd->file_descriptor, &cm, retbuffer); } else { ErrorToClient(hd, &cm) ; } // Signal to PingLoop that we're done. hd->toclient = toclient_complete ; if ( hd->ping_pipe[fd_pipe_write] != FILE_DESCRIPTOR_BAD ) { ignore_result = write( hd->ping_pipe[fd_pipe_write],"X",1) ; //dummy payload } TOCLIENTUNLOCK(hd); if (retbuffer) { owfree(retbuffer); } LEVEL_DEBUG("Finished with client request"); return VOID_RETURN; }