void Proxy::write() { log_packet(bOut, true, m_plugin->ProxyPacket); m_sock->write(bOut.data(0), bOut.size()); bOut.init(0); bOut.packetStart(); }
////////////////////// // rx_fetch_pkt: read packet into buffer if available // // returns number of bytes transferred to pkt, 0 if no data available // byte rx_fetch_pkt(pkt_t *pkt) { // Does the radio have business for us? if (!rx_pkt_ready()) return 0; // quick out if our packet interrupt hasn't fired if (!(rf_read_status() & (1<<IPKVALID))) { #ifdef RADIO_DEBUG sp("rx: int no pkt!"); #endif return 0; } #ifdef RADIO_DEBUG sp("rx_ got _packet"); #endif led_on(); byte length = rf_read_register(REG_RECEIVED_PACKET_LENGTH); // If the packet length is bigger than our buffer We Have A Situation. // Clip to our max packet size; set_rx_mode() will clear the fifo, // silently discarding the excess. // if (length > RF_PACKET_SIZE) length = RF_PACKET_SIZE; rx_get_pkt(REG_FIFO, length, pkt); rx_packet_count++; // got one? count it set_rx_mode(); led_off(); log_packet('R', pkt, length); return length; }
void YahooClient::packet_ready() { if (m_bHeader) { char header[4]; m_socket->readBuffer.unpack(header, 4); if (memcmp(header, YAHOO_PACKET_SIGN, 4)) { m_socket->error_state("Bad packet sign"); return; } m_socket->readBuffer.incReadPos(4); m_socket->readBuffer >> m_data_size >> m_service; unsigned long session_id; m_socket->readBuffer >> m_pkt_status >> session_id; if (m_data_size) { m_socket->readBuffer.add(m_data_size); m_bHeader = false; return; } } log_packet(m_socket->readBuffer, false, YahooPlugin::YahooPacket); process_packet(); m_socket->readBuffer.init(20); m_socket->readBuffer.packetStart(); m_bHeader = true; }
////////////////////// // rx_fetch_pkt: read packet into buffer if available // // returns number of bytes transferred to pkt, 0 if no data available // byte rx_fetch_pkt(pkt_t *pkt) { // Does the radio have business for us? //if (!vw_have_message()) return 0; // "If a message is available (good checksum or not), copies up to *len octets to buf. // Returns true if there was a message and the checksum was good." byte length = RF_PACKET_SIZE; if (!vw_get_message((uint8_t *) pkt, &length)) { //sp("rx: bad chksum\r\n"); return 0; } // If the packet length is bigger than our buffer We Have A Situation. // Clip to our max packet size, silently discarding the excess. // if (length > RF_PACKET_SIZE) { // todo: log here length = RF_PACKET_SIZE; } rx_packet_count++; // got one? count it #if defined(RADIO_DEBUG) log_packet('R', pkt, length); #endif return length; }
void YahooClient::sendPacket(unsigned short service, unsigned long status) { unsigned short size = 0; if (!m_values.empty()) { for (list<PARAM>::iterator it = m_values.begin(); it != m_values.end(); ++it) { size += 4; size += (*it).second.size(); size += number((*it).first).length(); } } m_socket->writeBuffer.packetStart(); m_socket->writeBuffer.pack(YAHOO_PACKET_SIGN, 4); m_socket->writeBuffer << 0x000B0000L << size << service << status << m_session; if (size) { for (list<PARAM>::iterator it = m_values.begin(); it != m_values.end(); ++it) { m_socket->writeBuffer << number((*it).first).c_str() << (unsigned short)0xC080 << (*it).second.c_str() << (unsigned short)0xC080; } } m_values.clear(); log_packet(m_socket->writeBuffer, true, YahooPlugin::YahooPacket); m_socket->write(); }
static int packet_parse(const uint8_t *buf, int idx, struct center_info *info) { int i; uint16_t temp_u16; log_packet(buf, idx); /* Byte 0: Always 0x02. */ /* Byte 1: Various status bits. */ info->rec = (buf[1] & (1 << 0)) != 0; info->mode_std = (((buf[1] >> 1) & 0x3) == 0); info->mode_max = (((buf[1] >> 1) & 0x3) == 1); info->mode_min = (((buf[1] >> 1) & 0x3) == 2); info->mode_maxmin = (((buf[1] >> 1) & 0x3) == 3); /* TODO: Rel. Not available on all models. */ info->t1t2 = (buf[1] & (1 << 3)) != 0; info->rel = (buf[1] & (1 << 4)) != 0; info->hold = (buf[1] & (1 << 5)) != 0; info->lowbat = (buf[1] & (1 << 6)) != 0; info->celsius = (buf[1] & (1 << 7)) != 0; /* Byte 2: Further status bits. */ info->memfull = (buf[2] & (1 << 0)) != 0; info->autooff = (buf[2] & (1 << 7)) != 0; /* Byte 7+8/9+10/11+12/13+14: channel T1/T2/T3/T4 temperature. */ for (i = 0; i < NUM_CHANNELS; i++) { temp_u16 = buf[8 + (i * 2)]; temp_u16 |= ((uint16_t)buf[7 + (i * 2)] << 8); info->temp[i] = (float)temp_u16; } /* Byte 43: Specifies whether we need to divide the value(s) by 10. */ for (i = 0; i < NUM_CHANNELS; i++) { /* Bit = 0: Divide by 10. Bit = 1: Don't divide by 10. */ if ((buf[43] & (1 << i)) == 0) info->temp[i] /= 10; } /* Bytes 39-42: Overflow/overlimit bits, depending on mode. */ for (i = 0; i < NUM_CHANNELS; i++) { if (info->mode_std && ((buf[39] & (1 << i)) != 0)) info->temp[i] = INFINITY; /* TODO: Rel. Not available on all models. */ // if (info->mode_rel && ((buf[40] & (1 << i)) != 0)) // info->temp[i] = INFINITY; if (info->mode_max && ((buf[41] & (1 << i)) != 0)) info->temp[i] = INFINITY; if (info->mode_min && ((buf[42] & (1 << i)) != 0)) info->temp[i] = INFINITY; /* TODO: Minmax? */ } /* Byte 44: Always 0x03. */ return SR_OK; }
static int write_frame(AVFormatContext *fmt_ctx, const AVRational *time_base, AVStream *st, AVPacket *pkt) { /* rescale output packet timestamp values from codec to stream timebase */ av_packet_rescale_ts(pkt, *time_base, st->time_base); pkt->stream_index = st->index; /* Write the compressed frame to the media file. */ log_packet(fmt_ctx, pkt); return av_interleaved_write_frame(fmt_ctx, pkt); }
void FetchClient::packet_ready() { if (m_socket->readBuffer.readPos() == m_socket->readBuffer.writePos()) return; log_packet(m_socket->readBuffer, false, HTTPPacket); for (;;){ if (m_state == Data){ unsigned size = m_socket->readBuffer.writePos() - m_socket->readBuffer.readPos(); if (size) m_res.pack(m_socket->readBuffer.data(m_socket->readBuffer.readPos()), size); if (m_res.size() >= m_size){ m_socket->error_state(""); return; } m_socket->readBuffer.init(0); m_socket->readBuffer.packetStart(); return; } string line; if (!read_line(line)){ m_socket->readBuffer.init(0); m_socket->readBuffer.packetStart(); return; } switch (m_state){ case None: #ifdef USE_OPENSSL case SSLConnect: #endif if (getToken(line, ' ').substr(0, 5) != "HTTP/"){ m_socket->error_state("Bad HTTP answer"); return; } m_code = atol(getToken(line, ' ').c_str()); m_state = Header; break; case Header: if (line.empty()){ m_state = Data; break; } m_hIn += line; m_hIn += '\x00'; if (getToken(line, ':') == "Content-Length"){ const char *p; for (p = line.c_str(); *p; p++) if (*p != ' ') break; m_size = atol(p); } break; default: break; } } }
////////////////////// // // tx_send_packet: transmit a data packet // // length: length of raw packet including header // pkt: pointer to packet // void tx_send_pkt(pkt_t *pkt, uint8_t length) { #if defined(RADIO_DEBUG) log_packet('T', pkt, length); #endif vw_wait_tx(); // wait for tx idle vw_send((uint8_t *) pkt, length); // todo: handle error here tx_packet_count++; }
void Proxy::read(unsigned size, unsigned minsize) { bIn.init(size); bIn.packetStart(); int readn = m_sock->read(bIn.data(0), size); if ((readn != (int)size) || (minsize && (readn < (int)minsize))){ if (notify) notify->error_state(I18N_NOOP("Error proxy read")); return; } log_packet(bIn, false, m_plugin->ProxyPacket); }
/* Returns 1 upon sent request; 0 upon serious error and 2 upon disconnect */ void peer_sendreq(struct peer_t *p, struct request_t *r) { int ret; r->active = SENT; /* BUG: even if the write below fails? */ /* QUASIBUG Busy-waiting on the network buffer to free up some space is not acceptable; at best, it wastes CPU; at worst, it hangs the daemon until the TCP timeout informs it that its connection to Tor has timed out. (Although that’s an unlikely failure mode.) */ /* BUG: what if write() doesn't write all the data? */ /* This is writing data to the remote DNS server over Tor with TCP */ while ((ret = write(p->tcp_fd, r->b, (r->bl + 2))) < 0 && errno == EAGAIN); if (ret == 0) { peer_mark_as_dead(p); log_packet(r->id, TCP, DROP_OUT, PEER_IP(p), PEER_PORT(p)); } log_packet(r->id, TCP, OUT, PEER_IP(p), PEER_PORT(p)); }
/* * Inject packets. */ static void allow_packets(bool log, struct ethhdr **packets) { for (int i = 0; packets[i] != NULL; i++) { struct iphdr *ip_header = (struct iphdr *)(packets[i] + 1); size_t tot_len = sizeof(struct ethhdr) + ntohs(ip_header->tot_len); if (log) log_packet((uint8_t *)ip_header); inject_packet((uint8_t *)packets[i], tot_len); } }
/* * fsm_rconfnakrej - Receive Configure-Nak or Configure-Reject. */ static void fsm_rconfnakrej(fsm *f, int code, int id, u_char *inp, int len) { int (*proc)(fsm *, u_char *, int); int ret; FSMDEBUG((LOG_INFO, "fsm_rconfnakrej(%s): Rcvd id %d.", PROTO_NAME(f), id)); if (id != f->reqid || f->seen_ack) /* Expected id? */ return; /* Nope, toss... */ proc = (code == CONFNAK)? f->callbacks->nakci: f->callbacks->rejci; if (!proc || !(ret = proc(f, inp, len))) { /* Nak/reject is bad - ignore it */ log_packet(inp, len, "Received bad configure-nak/rej: ", LOG_ERR); FSMDEBUG((LOG_INFO, "%s: received bad %s (length %d)", PROTO_NAME(f), (code==CONFNAK? "Nak": "reject"), len)); return; } f->seen_ack = 1; switch (f->state) { case CLOSED: case STOPPED: fsm_sdata(f, TERMACK, id, NULL, 0); break; case REQSENT: case ACKSENT: /* They didn't agree to what we wanted - try another request */ UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ if (ret < 0) f->state = STOPPED; /* kludge for stopping CCP */ else fsm_sconfreq(f, 0); /* Send Configure-Request */ break; case ACKRCVD: /* Got a Nak/reject when we had already had an Ack?? oh well... */ UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ fsm_sconfreq(f, 0); f->state = REQSENT; break; case OPENED: /* Go down and restart negotiation */ if (f->callbacks->down) (*f->callbacks->down)(f); /* Inform upper layers */ fsm_sconfreq(f, 0); /* Send initial Configure-Request */ f->state = REQSENT; break; } }
void Listener::read(unsigned size, unsigned minsize) { bIn.init(size); bIn.packetStart(); int readn = m_sock->read(bIn.data(0), size); if ((readn != (int)size) || (minsize && (readn < (int)minsize))){ if (notify && notify->error("Error proxy read")) delete notify; return; } log_packet(bIn, false, m_plugin->ProxyPacket); }
void JabberClient::packet_ready() { if (m_socket->readBuffer.writePos() == 0) return; JabberPlugin *plugin = static_cast<JabberPlugin*>(protocol()->plugin()); log_packet(m_socket->readBuffer, false, plugin->JabberPacket); if (XML_Parse(m_parser, m_socket->readBuffer.data(), m_socket->readBuffer.writePos(), false) != XML_STATUS_OK) m_socket->error_state("XML parse error"); m_socket->readBuffer.init(0); m_socket->readBuffer.packetStart(); }
/* * fsm_rconfack - Receive Configure-Ack. */ static void fsm_rconfack(fsm *f, int id, u_char *inp, int len) { FSMDEBUG((LOG_INFO, "fsm_rconfack(%s): Rcvd id %d.", PROTO_NAME(f), id)); if (id != f->reqid || f->seen_ack) /* Expected id? */ return; /* Nope, toss... */ if( !(f->callbacks->ackci? (*f->callbacks->ackci)(f, inp, len): (len == 0)) ){ /* Ack is bad - ignore it */ log_packet(inp, len, "Received bad configure-ack: ", LOG_ERR); FSMDEBUG((LOG_INFO, "%s: received bad Ack (length %d)", PROTO_NAME(f), len)); return; } f->seen_ack = 1; switch (f->state) { case CLOSED: case STOPPED: fsm_sdata(f, TERMACK, id, NULL, 0); break; case REQSENT: f->state = ACKRCVD; f->retransmits = f->maxconfreqtransmits; break; case ACKRCVD: /* Huh? an extra valid Ack? oh well... */ UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ fsm_sconfreq(f, 0); f->state = REQSENT; break; case ACKSENT: UNTIMEOUT(fsm_timeout, f); /* Cancel timeout */ f->state = OPENED; f->retransmits = f->maxconfreqtransmits; if (f->callbacks->up) (*f->callbacks->up)(f); /* Inform upper layers */ break; case OPENED: /* Go down and restart negotiation */ if (f->callbacks->down) (*f->callbacks->down)(f); /* Inform upper layers */ fsm_sconfreq(f, 0); /* Send initial Configure-Request */ f->state = REQSENT; break; } }
static int write_frame(AVFormatContext *fmt_ctx, const AVRational *time_base, AVStream *st, AVPacket *pkt) { /* rescale output packet timestamp values from codec to stream timebase */ pkt->pts = av_rescale_q_rnd(pkt->pts, *time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); pkt->dts = av_rescale_q_rnd(pkt->dts, *time_base, st->time_base, AV_ROUND_NEAR_INF|AV_ROUND_PASS_MINMAX); pkt->duration = av_rescale_q(pkt->duration, *time_base, st->time_base); pkt->stream_index = st->index; /* Write the compressed frame to the media file. */ log_packet(fmt_ctx, pkt); return av_interleaved_write_frame(fmt_ctx, pkt); }
/************************************************************************** Updates pplayer->attribute_block according to the given packet. **************************************************************************/ void generic_handle_player_attribute_chunk(struct player *pplayer, const struct packet_player_attribute_chunk *chunk) { log_packet("received attribute chunk %u/%u %u", (unsigned int) chunk->offset, (unsigned int) chunk->total_length, (unsigned int) chunk->chunk_length); if (chunk->total_length < 0 || chunk->chunk_length < 0 || chunk->total_length >= MAX_ATTRIBUTE_BLOCK || chunk->offset < 0 || chunk->offset > chunk->total_length /* necessary check on 32 bit systems */ || chunk->chunk_length > chunk->total_length || chunk->offset + chunk->chunk_length > chunk->total_length || (chunk->offset != 0 && chunk->total_length != pplayer->attribute_block_buffer.length)) { /* wrong attribute data */ if (pplayer->attribute_block_buffer.data) { free(pplayer->attribute_block_buffer.data); pplayer->attribute_block_buffer.data = NULL; } pplayer->attribute_block_buffer.length = 0; log_error("Received wrong attribute chunk"); return; } /* first one in a row */ if (chunk->offset == 0) { if (pplayer->attribute_block_buffer.data) { free(pplayer->attribute_block_buffer.data); pplayer->attribute_block_buffer.data = NULL; } pplayer->attribute_block_buffer.data = fc_malloc(chunk->total_length); pplayer->attribute_block_buffer.length = chunk->total_length; } memcpy((char *) (pplayer->attribute_block_buffer.data) + chunk->offset, chunk->data, chunk->chunk_length); if (chunk->offset + chunk->chunk_length == chunk->total_length) { /* Received full attribute block */ if (pplayer->attribute_block.data != NULL) { free(pplayer->attribute_block.data); } pplayer->attribute_block.data = pplayer->attribute_block_buffer.data; pplayer->attribute_block.length = pplayer->attribute_block_buffer.length; pplayer->attribute_block_buffer.data = NULL; pplayer->attribute_block_buffer.length = 0; } }
void process_incoming_request(struct request_t *tmp) { // get request id unsigned short int *ul = (unsigned short int*) (tmp->b + 2); tmp->rid = tmp->id = ntohs(*ul); // get request length ul = (unsigned short int*)tmp->b; *ul = htons(tmp->bl); log_packet(tmp->rid, UDP, IN, REQ_IP(tmp), REQ_PORT(tmp)); request_add(tmp); // This should be checked; we're currently ignoring important returns. }
static void ChallengeResponse( u_char *challenge, /* IN 8 octets */ u_char *pwHash, /* IN 16 octets */ u_char *response /* OUT 24 octets */) { u_char ZPasswordHash[21]; BZERO(ZPasswordHash, sizeof(ZPasswordHash)); BCOPY(pwHash, ZPasswordHash, 16); #if 0 log_packet(ZPasswordHash, sizeof(ZPasswordHash), "ChallengeResponse - ZPasswordHash", LOG_DEBUG); #endif DesEncrypt(challenge, ZPasswordHash + 0, response + 0); DesEncrypt(challenge, ZPasswordHash + 7, response + 8); DesEncrypt(challenge, ZPasswordHash + 14, response + 16); #if 0 log_packet(response, 24, "ChallengeResponse - response", LOG_DEBUG); #endif }
/************************************************************************** Test and log for sending player attribute_block **************************************************************************/ void pre_send_packet_player_attribute_chunk(struct connection *pc, struct packet_player_attribute_chunk *packet) { fc_assert(packet->total_length > 0 && packet->total_length < MAX_ATTRIBUTE_BLOCK); /* 500 bytes header, just to be sure */ fc_assert(packet->chunk_length > 0 && packet->chunk_length < MAX_LEN_PACKET - 500); fc_assert(packet->chunk_length <= packet->total_length); fc_assert(packet->offset >= 0 && packet->offset < packet->total_length); log_packet("sending attribute chunk %d/%d %d", packet->offset, packet->total_length, packet->chunk_length); }
void * madns_response(MADNS * mp, in_addr_t * ip) { while (1) { char pkt[DNS_PACKET_LEN]; INADDR sa; socklen_t salen = sizeof sa; RESPONSE resp; char ips[99]; int len = recvfrom(mp->sock, pkt, sizeof pkt, 0, (SADDR *) & sa, &salen); if (len <= 0) break; if (!parse_response(pkt, len, &resp)) continue; LOG("resp: ip %s ttl %lu tid %hu name %s\n", ipstr(resp.ip, ips), resp.ttl, resp.tid, resp.name); QUERY *qp = &mp->queries[(int)resp.tid % mp->qsize]; if (qp->ctx && qp->tid == resp.tid && qp->server && qp->server->ip == sa.sin_addr.s_addr) { if (resp.ip != INADDR_ANY && !strcasecmp(resp.name, qp->name)) update_cache(mp, &resp); return destroy_query(mp, qp, *ip = resp.ip); } log_packet(__LINE__, pkt, len); if (qp->server && qp->server->ip != sa.sin_addr.s_addr) LOG("resp.addr=%s tid=%hu ttl=%lu serv=%s\n", ipstr(sa.sin_addr.s_addr, pkt), resp.tid, resp.ttl, ipstr(qp->server->ip, pkt + 33)); } if (!qempty(&mp->active)) { QUERY *qp = link_QUERY(mp->active.next); if (qp->expires <= time(0)) return destroy_query(mp, qp, *ip = INADDR_ANY); } return NULL; }
void output (int unit, unsigned char *p, int len) { if (unit != 0) { MAINDEBUG((LOG_WARNING, "output: unit != 0!")); } if (debug) { log_packet(p, len, "sent "); } if (write(fd, p, len) < 0) { syslog(LOG_ERR, "write: %m"); die(1); } }
static int action_log(struct mbuf **mb, userfw_chk_args *args, userfw_action *action, userfw_cache *cache, int *continue_, uint32_t flags) { int ret = 0; *continue_ = 1; VERIFY_OPCODE2(action, USERFW_LOG_MOD, A_LOG, A_LOG_AND, 0); if ((flags & USERFW_ACTION_FLAG_SECOND_PASS) == 0) { log_packet(mb, args, (action->op == A_LOG) ? action : action->args[0].action.p, cache); if (action->op == A_LOG_AND) ret = action->args[0].action.p->do_action(mb, args, action->args[0].action.p, cache, continue_, flags); } return ret; }
static void receive_and_log_packet() { char buf[UDP_RECEIVE_BUFFER_SIZE]; struct sockaddr from; socklen_t fromlen; ssize_t len; fromlen = sizeof( from ); len = recvfrom( listening_socket, buf, UDP_RECEIVE_BUFFER_SIZE, 0, &from, &fromlen ); if ( len != -1 ) { printf("\t<packet>\n"); log_packet( buf, len ); printf("\t</packet>\n\n"); fflush( stdout ); } }
/************************************************************************** Sanity check packet **************************************************************************/ bool packet_check(struct data_in *din, struct connection *pc) { size_t rem = dio_input_remaining(din); if (rem > 0) { int type, len; dio_input_rewind(din); dio_get_type(din, pc->packet_header.length, &len); dio_get_type(din, pc->packet_header.type, &type); log_packet("received long packet (type %d, len %d, rem %lu) from %s", type, len, (unsigned long) rem, conn_description (pc)); return FALSE; } return TRUE; }
bool HTTPS_Proxy::readLine(string &s) { for (;;){ char c; int n = m_sock->read(&c, 1); if (n < 0){ error_state(ANSWER_ERROR, m_plugin->ProxyErr); return false; } if (n == 0) return false; if (c == '\r') continue; if (c == '\n') break; bIn << c; } log_packet(bIn, false, m_plugin->ProxyPacket); s.assign(bIn.data(0), bIn.size()); bIn.init(0); bIn.packetStart(); return true; }
void FetchClient::connect_ready() { #ifdef USE_OPENSSL if (m_state == None){ m_socket->setRaw(true); m_socket->readBuffer.init(0); HTTPSClient *https = new HTTPSClient(m_socket->socket()); if (!https->init()){ m_socket->error_state("Can't initialize HTTPS"); return; } m_state = SSLConnect; m_socket->setSocket(https); https->connect(); https->process(); return; } #endif log(L_DEBUG, "HTTP connect ready"); m_socket->setRaw(true); m_socket->writeBuffer.packetStart(); m_socket->writeBuffer << (m_post ? "POST " : "GET ") << m_uri.c_str() << " HTTP/1.0\r\n"; for (HEADERS_MAP::iterator it = m_hOut.begin(); it != m_hOut.end(); ++it){ m_socket->writeBuffer << (*it).first.c_str() << ": " << (*it).second.c_str() << "\r\n"; } m_socket->writeBuffer << "\r\n"; if (m_post) m_socket->writeBuffer.pack(m_post->data(), m_post->size()); log_packet(m_socket->writeBuffer, true, HTTPPacket); m_socket->write(); m_socket->readBuffer.init(0); m_socket->readBuffer.packetStart(); }
////////////////////// // tx_send_packet: transmit a data packet // // length: length of raw packet including header // pkt: pointer to packet // void tx_send_pkt(pkt_t *pkt, uint8_t length) { log_packet('T', pkt, length); led_on(); set_tx_packet_length(length); tx_send_payload(0x80 + REG_FIFO, length, (uint8_t *)pkt); // Clock out payload // Set TXON bit to start the tx cycle tx_start(); led_off(); led_on(); // toggle to note time to here tx_packet_count++; // wait for the packet transmission to complete // per p.81 TXON is "Automatically cleared in FIFO mode once the packet is sent" // we spin for about 10ms here... while (!rf_interrupt()) {;} rf_read_status(); // TODO: consider a better place to restore // this one wastes time going back into rx mode during long prints set_rx_mode(); led_off(); }
void JabberClient::sendPacket() { JabberPlugin *plugin = static_cast<JabberPlugin*>(protocol()->plugin()); log_packet(m_socket->writeBuffer, true, plugin->JabberPacket); m_socket->write(); }