void connection::handshake_received(const boost::system::error_code& error, std::size_t bytes_transferred) { if (error) { stillborn(); return; } link_.received(bytes_transferred); bool handshake_valid; if (link_.socket.lowest_layer().remote_endpoint().address().is_v4()) handshake_valid = do_parse_handshake<ip::address_v4>(); else handshake_valid = do_parse_handshake<ip::address_v6>(); if (!handshake_valid) { link_.socket.lowest_layer().close(); DLOG(INFO) << "Error parsing handshake"; return; } remote_identity_ = network_key(::SSL_get_peer_certificate(link_.socket.impl()->ssl)); if (supported_protocols_.size() * 2 > link_.valid_received_bytes()) boost::asio::async_read(link_.socket, mutable_buffers_1(link_.receive_buffer()), boost::asio::transfer_at_least(supported_protocols_.size() - link_.valid_received_bytes()), boost::bind(&connection::complete_connection, shared_from_this(), placeholders::error, placeholders::bytes_transferred)); else complete_connection(error, 0); }
/* * ECONNRESET == RST in TCP world. Check what equivalent * events can happen in ATM world. * * Returns < 0 for error */ static int check_connection(int slot) { char buff[MAX_PACKET_LENGTH]; struct k_message *msg; struct pollfd *pfd; int bytes_read; dprintf("mpcd: io.c: check_connection() event in fd %d, type %d\n", fds[slot].fd, socket_type[slot]); if (socket_type[slot] & CONNECTING) { /* connect() completed (maybe) */ complete_connection(slot); /* ignore return value */ return 0; } pfd = &fds[slot]; bytes_read = read(pfd->fd, buff, sizeof(buff)); if (bytes_read < 0) { if (errno == ECONNRESET || errno == EPIPE) { /* conn reset by the other end or kernel (EPIPE) */ if (socket_type[slot] & OUTGOING_SHORTCUT) update_ingress_entry(NULL, pfd->fd, INGRESS_NOT_USED); close(pfd->fd); pfd->fd = -1; socket_type[slot] = NOT_USED; return 1; } printf("mpcd: io.c: check_connection() bytes_read=%d, errno='%s'\n", bytes_read, strerror(errno)); return -1; } if (bytes_read == 0) { /* conn closed by the other end */ if (socket_type[slot] & OUTGOING_SHORTCUT) update_ingress_entry(NULL, pfd->fd, INGRESS_NOT_USED); dprintf("mpcd: io.c: check_connection() fd %d type %d; connection closed'\n", pfd->fd, socket_type[slot]); close(pfd->fd); pfd->fd = -1; socket_type[slot] = NOT_USED; return 1; } /* See if this is a MPOA control packet */ if ( memcmp(buff, &llc_snap_mpoa_ctrl, sizeof(llc_snap_mpoa_ctrl)) == 0 ) if ( recognize_packet(buff + sizeof(llc_snap_mpoa_ctrl)) >= 0) return 1; dprintf("mpcd: io.c check_connection(): msg from kernel\n"); msg = (struct k_message *)buff; if(msg->type == DATA_PLANE_PURGE){ send_purge_request(msg->content.eg_info.mps_ip,32, get_own_ip_addr(mpc_control.INTERFACE_NUMBER),pfd->fd); return 1; } printf("mpcd: io.c check_connection(): unknown msg %d from kernel, ignoring", msg->type); return 1; }