//update frames for many vertex position changes //assumes this is the first piece of thread void ThreadPiece::updateFrames_all() { update_edge(); update_bishop_frame_firstPiece(); ThreadPiece* curr_piece = _next_piece; #ifdef ISOTROPIC for ( ; curr_piece->_next_piece != NULL; curr_piece = curr_piece->_next_piece) { curr_piece->update_edge(); curr_piece->update_bishop_frame(); } curr_piece = curr_piece->_prev_piece; curr_piece->_angle_twist += curr_piece->twist_angle_error(); #else update_material_frame(); double twist_to_add = 0; for ( ; curr_piece->_next_piece != NULL; curr_piece = curr_piece->_next_piece) { curr_piece->update_edge(); curr_piece->update_bishop_frame(); curr_piece->_angle_twist += twist_to_add; double this_err = curr_piece->twist_angle_error(); twist_to_add += this_err; curr_piece->_angle_twist += this_err; curr_piece->update_material_frame(); } #endif }
//not applicable for first 2 or last 2 pieces void ThreadPiece::updateFrames() { /*if (_prev_piece == NULL || _prev_piece->_prev_piece == NULL || _next_piece == NULL || _next_piece->_next_piece == NULL) { std::cerr << "shouldn't call updateFrames() on the first 2 or last 2 pieces!" << std::endl; exit(0); }*/ _prev_piece->update_edge(); update_edge(); ThreadPiece* to_change_bishop = _prev_piece; while (to_change_bishop->_next_piece != NULL) { to_change_bishop->update_bishop_frame(); to_change_bishop = to_change_bishop->_next_piece; } #ifdef ISOTROPIC //angle of last piece is the only one that matters to_change_bishop = to_change_bishop->_prev_piece; to_change_bishop->_angle_twist += to_change_bishop->twist_angle_error(); #else //twist angle may have changed double angle_twist_diff = _next_piece->twist_angle_error(); //_prev_piece->_angle_twist += angle_twist_diff/3.0; _prev_piece->update_material_frame(); //_angle_twist += 2.0*angle_twist_diff/3.0; update_material_frame(); ThreadPiece* to_change_twist = _next_piece; while (to_change_twist->_next_piece != NULL) { to_change_twist->_angle_twist += angle_twist_diff; to_change_twist = to_change_twist->_next_piece; } #endif }
//THIS MAKES THREAD DATA INCONSISTENT! Careful when using void ThreadPiece::offset_and_update_locally(const Vector3d& offset) { //offset this vertex (call it vertex i) _vertex += offset; #ifdef ISOTROPIC updateFrames(); #else //calculate the locally changed edges and bishop frames (from i-1 to i+1) if (_prev_piece != NULL) { _prev_piece->update_edge(); if (_prev_piece->_prev_piece != NULL) { _prev_piece->update_bishop_frame(); _prev_piece->update_material_frame(); } } if (_next_piece != NULL) { update_edge(); if (_prev_piece != NULL) { update_bishop_frame(); } if (_next_piece->_next_piece != NULL) { _next_piece->update_bishop_frame(); //find how the change in bishop frame affects the angle change update_material_frame(); double angle_twist_diff = _next_piece->twist_angle_error(); // std::cout << "angle twist diff: " << angle_twist_diff << std::endl; _next_piece->_angle_twist += angle_twist_diff; //_next_piece->update_material_frame(); } } #endif }
//assumes the angles are correct, and calculates the material frames void ThreadPiece::initializeFrames() { if (_next_piece == NULL) { // update_bishop_frame_lastPiece(); // update_material_frame(); return; } update_edge(); //now update bishop and material frames if (_prev_piece != NULL) { update_bishop_frame(); update_material_frame(); } else { update_bishop_frame_firstPiece(); update_material_frame(); } _next_piece->initializeFrames(); }
// Needs Y to only change once (looser than convex in X) static void walk_simple_edges(SkEdge* prevHead, SkBlitter* blitter, int start_y, int stop_y) { validate_sort(prevHead->fNext); SkEdge* leftE = prevHead->fNext; SkEdge* riteE = leftE->fNext; SkEdge* currE = riteE->fNext; #if 0 int local_top = leftE->fFirstY; SkASSERT(local_top == riteE->fFirstY); #else // our edge choppers for curves can result in the initial edges // not lining up, so we take the max. int local_top = SkMax32(leftE->fFirstY, riteE->fFirstY); #endif ASSERT_RETURN(local_top >= start_y); while (local_top < stop_y) { SkASSERT(leftE->fFirstY <= stop_y); SkASSERT(riteE->fFirstY <= stop_y); int local_bot = SkMin32(leftE->fLastY, riteE->fLastY); local_bot = SkMin32(local_bot, stop_y - 1); ASSERT_RETURN(local_top <= local_bot); SkFixed left = leftE->fX; SkFixed dLeft = leftE->fDX; SkFixed rite = riteE->fX; SkFixed dRite = riteE->fDX; int count = local_bot - local_top; ASSERT_RETURN(count >= 0); if (0 == (dLeft | dRite)) { int L = SkFixedRoundToInt(left); int R = SkFixedRoundToInt(rite); if (L > R) { std::swap(L, R); } if (L < R) { count += 1; blitter->blitRect(L, local_top, R - L, count); } local_top = local_bot + 1; } else { do { int L = SkFixedRoundToInt(left); int R = SkFixedRoundToInt(rite); if (L > R) { std::swap(L, R); } if (L < R) { blitter->blitH(L, local_top, R - L); } // Either/both of these might overflow, since we perform this step even if // (later) we determine that we are done with the edge, and so the computed // left or rite edge will not be used (see update_edge). Use this helper to // silence UBSAN when we perform the add. left = Sk32_can_overflow_add(left, dLeft); rite = Sk32_can_overflow_add(rite, dRite); local_top += 1; } while (--count >= 0); } leftE->fX = left; riteE->fX = rite; if (!update_edge(leftE, local_bot)) { if (currE->fFirstY >= stop_y) { return; // we're done } leftE = currE; currE = currE->fNext; ASSERT_RETURN(leftE->fFirstY == local_top); } if (!update_edge(riteE, local_bot)) { if (currE->fFirstY >= stop_y) { return; // we're done } riteE = currE; currE = currE->fNext; ASSERT_RETURN(riteE->fFirstY == local_top); } } }
/** Examine a datagram and determine what to do with it. * */ static int process_udp( n2n_sn_t * sss, const struct sockaddr_in * sender_sock, const uint8_t * udp_buf, size_t udp_size, time_t now) { n2n_common_t cmn; /* common fields in the packet header */ size_t rem; size_t idx; size_t msg_type; uint8_t from_supernode; macstr_t mac_buf; macstr_t mac_buf2; n2n_sock_str_t sockbuf; traceEvent( TRACE_DEBUG, "process_udp(%lu)", udp_size ); /* Use decode_common() to determine the kind of packet then process it: * * REGISTER_SUPER adds an edge and generate a return REGISTER_SUPER_ACK * * REGISTER, REGISTER_ACK and PACKET messages are forwarded to their * destination edge. If the destination is not known then PACKETs are * broadcast. */ rem = udp_size; /* Counts down bytes of packet to protect against buffer overruns. */ idx = 0; /* marches through packet header as parts are decoded. */ if ( decode_common(&cmn, udp_buf, &rem, &idx) < 0 ) { traceEvent( TRACE_ERROR, "Failed to decode common section" ); return -1; /* failed to decode packet */ } msg_type = cmn.pc; /* packet code */ from_supernode= cmn.flags & N2N_FLAGS_FROM_SUPERNODE; if ( cmn.ttl < 1 ) { traceEvent( TRACE_WARNING, "Expired TTL" ); return 0; /* Don't process further */ } --(cmn.ttl); /* The value copied into all forwarded packets. */ if ( msg_type == MSG_TYPE_PACKET ) { /* PACKET from one edge to another edge via supernode. */ /* pkt will be modified in place and recoded to an output of potentially * different size due to addition of the socket.*/ n2n_PACKET_t pkt; n2n_common_t cmn2; uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; size_t encx=0; int unicast; /* non-zero if unicast */ const uint8_t * rec_buf; /* either udp_buf or encbuf */ sss->stats.last_fwd=now; decode_PACKET( &pkt, &cmn, udp_buf, &rem, &idx ); unicast = (0 == is_multi_broadcast(pkt.dstMac) ); traceEvent( TRACE_DEBUG, "Rx PACKET (%s) %s -> %s %s", (unicast?"unicast":"multicast"), macaddr_str( mac_buf, pkt.srcMac ), macaddr_str( mac_buf2, pkt.dstMac ), (from_supernode?"from sn":"local") ); if ( !from_supernode ) { memcpy( &cmn2, &cmn, sizeof( n2n_common_t ) ); /* We are going to add socket even if it was not there before */ cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; pkt.sock.family = AF_INET; pkt.sock.port = ntohs(sender_sock->sin_port); memcpy( pkt.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE ); rec_buf = encbuf; /* Re-encode the header. */ encode_PACKET( encbuf, &encx, &cmn2, &pkt ); /* Copy the original payload unchanged */ encode_buf( encbuf, &encx, (udp_buf + idx), (udp_size - idx ) ); } else { /* Already from a supernode. Nothing to modify, just pass to * destination. */ traceEvent( TRACE_DEBUG, "Rx PACKET fwd unmodified" ); rec_buf = udp_buf; encx = udp_size; } /* Common section to forward the final product. */ if ( unicast ) { try_forward( sss, &cmn, pkt.dstMac, rec_buf, encx ); } else { try_broadcast( sss, &cmn, pkt.srcMac, rec_buf, encx ); } }/* MSG_TYPE_PACKET */ else if ( msg_type == MSG_TYPE_REGISTER ) { /* Forwarding a REGISTER from one edge to the next */ n2n_REGISTER_t reg; n2n_common_t cmn2; uint8_t encbuf[N2N_SN_PKTBUF_SIZE]; size_t encx=0; int unicast; /* non-zero if unicast */ const uint8_t * rec_buf; /* either udp_buf or encbuf */ sss->stats.last_fwd=now; decode_REGISTER( ®, &cmn, udp_buf, &rem, &idx ); unicast = (0 == is_multi_broadcast(reg.dstMac) ); if ( unicast ) { traceEvent( TRACE_DEBUG, "Rx REGISTER %s -> %s %s", macaddr_str( mac_buf, reg.srcMac ), macaddr_str( mac_buf2, reg.dstMac ), ((cmn.flags & N2N_FLAGS_FROM_SUPERNODE)?"from sn":"local") ); if ( 0 != (cmn.flags & N2N_FLAGS_FROM_SUPERNODE) ) { memcpy( &cmn2, &cmn, sizeof( n2n_common_t ) ); /* We are going to add socket even if it was not there before */ cmn2.flags |= N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; reg.sock.family = AF_INET; reg.sock.port = ntohs(sender_sock->sin_port); memcpy( reg.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE ); rec_buf = encbuf; /* Re-encode the header. */ encode_REGISTER( encbuf, &encx, &cmn2, ® ); /* Copy the original payload unchanged */ encode_buf( encbuf, &encx, (udp_buf + idx), (udp_size - idx ) ); } else { /* Already from a supernode. Nothing to modify, just pass to * destination. */ rec_buf = udp_buf; encx = udp_size; } try_forward( sss, &cmn, reg.dstMac, rec_buf, encx ); /* unicast only */ } else { traceEvent( TRACE_ERROR, "Rx REGISTER with multicast destination" ); } } else if ( msg_type == MSG_TYPE_REGISTER_ACK ) { traceEvent( TRACE_DEBUG, "Rx REGISTER_ACK (NOT IMPLEMENTED) SHould not be via supernode" ); } else if ( msg_type == MSG_TYPE_REGISTER_SUPER ) { n2n_REGISTER_SUPER_t reg; n2n_REGISTER_SUPER_ACK_t ack; n2n_common_t cmn2; uint8_t ackbuf[N2N_SN_PKTBUF_SIZE]; size_t encx=0; /* Edge requesting registration with us. */ sss->stats.last_reg_super=now; ++(sss->stats.reg_super); decode_REGISTER_SUPER( ®, &cmn, udp_buf, &rem, &idx ); cmn2.ttl = N2N_DEFAULT_TTL; cmn2.pc = n2n_register_super_ack; cmn2.flags = N2N_FLAGS_SOCKET | N2N_FLAGS_FROM_SUPERNODE; memcpy( cmn2.community, cmn.community, sizeof(n2n_community_t) ); memcpy( &(ack.cookie), &(reg.cookie), sizeof(n2n_cookie_t) ); memcpy( ack.edgeMac, reg.edgeMac, sizeof(n2n_mac_t) ); ack.lifetime = reg_lifetime( sss ); ack.sock.family = AF_INET; ack.sock.port = ntohs(sender_sock->sin_port); memcpy( ack.sock.addr.v4, &(sender_sock->sin_addr.s_addr), IPV4_SIZE ); ack.num_sn=0; /* No backup */ memset( &(ack.sn_bak), 0, sizeof(n2n_sock_t) ); traceEvent( TRACE_DEBUG, "Rx REGISTER_SUPER for %s [%s]", macaddr_str( mac_buf, reg.edgeMac ), sock_to_cstr( sockbuf, &(ack.sock) ) ); update_edge( sss, reg.edgeMac, cmn.community, &(ack.sock), now ); #ifdef N2N_MULTIPLE_SUPERNODES { struct comm_info *ci = comm_find(sss->communities.list_head, cmn.community, strlen((const char *) cmn.community)); if (ci) { ack.num_sn = ci->sn_num; memcpy(&ack.sn_bak, ci->sn_sock, ci->sn_num * sizeof(n2n_sock_t)); } } #endif encode_REGISTER_SUPER_ACK( ackbuf, &encx, &cmn2, &ack ); sendto( sss->sock, ackbuf, encx, 0, (struct sockaddr *)sender_sock, sizeof(struct sockaddr_in) ); traceEvent( TRACE_DEBUG, "Tx REGISTER_SUPER_ACK for %s [%s]", macaddr_str( mac_buf, reg.edgeMac ), sock_to_cstr( sockbuf, &(ack.sock) ) ); } return 0; }