예제 #1
0
파일: tunnelc.go 프로젝트: kitech/toxtun
func (this *Tunnelc) onToxnetFriendLossyPacket(t *tox.Tox, friendNumber uint32, message string, userData interface{}) {
	debug.Println(friendNumber, len(message), gopp.StrSuf(message, 52))
	buf := bytes.NewBufferString(message).Bytes()
	if buf[0] == 254 { // lossypacket
		buf = buf[1:]
		var conv uint32
		// kcp包前4字段为conv,little hacky
		if len(buf) < 4 {
			errl.Println("wtf")
		}
		conv = binary.LittleEndian.Uint32(buf)
		ch := this.chpool.pool2[conv]
		if ch == nil {
			info.Println("channel not found, maybe has some problem, maybe already closed", conv)
			// TODO 应该给服务器回个关闭包
			// TODO 这个地方发送的包容易出现重复,但是需要服务端处理
			pkt := NewBrokenPacket(conv)
			ch := NewChannelFromPacket(pkt)
			newpkt := ch.makeCloseFINPacket()
			this.tox.FriendSendMessage(friendNumber, string(newpkt.toJson()))
		} else {
			n := ch.kcp.Input(buf)
			debug.Println("tox->kcp:", conv, n, len(buf), gopp.StrSuf(string(buf), 52))
		}
	} else {
		info.Println("unknown message:", buf[0])
	}
}
예제 #2
0
파일: tunneld.go 프로젝트: kitech/toxtun
func (this *Tunneld) processKcpReadyRead(ch *Channel) {
	if ch.conn == nil {
		errl.Println("Not Connected:", ch.chidsrv, ch.chidcli)
		// return
	}

	buf := make([]byte, ch.kcp.PeekSize())
	n := ch.kcp.Recv(buf)

	if len(buf) != n {
		errl.Println("Invalide kcp recv data")
	}

	pkt := parsePacket(buf)
	if pkt.isconnack() {
	} else if pkt.isdata() {
		ch := this.chpool.pool[pkt.chidsrv]
		debug.Println("processing channel data:", ch.chidsrv, len(pkt.data), gopp.StrSuf(pkt.data, 52))
		buf, err := base64.StdEncoding.DecodeString(pkt.data)
		if err != nil {
			errl.Println(err)
		}

		wn, err := ch.conn.Write(buf)
		if err != nil {
			errl.Println(err)
		}
		debug.Println("kcp->srv:", wn)
		appevt.Trigger("reqbytes", wn, len(buf)+25)
	} else {
	}
}
예제 #3
0
파일: tunneld.go 프로젝트: kitech/toxtun
func (this *Tunneld) processUdpReadyRead(addr net.Addr, buf []byte, size int) {
	// info.Println(addr, string(buf), size)
	debug.Println(addr, string(buf), size)
	// kcp包前4字段为conv,little hacky
	if len(buf) < 4 {
		errl.Println("wtf")
	}

	// maybe check ping packet

	// unpack kcp package
	conv := binary.LittleEndian.Uint32(buf)
	ch := this.chpool.pool2[conv]
	if ch == nil {
		errl.Println("channel not found, maybe has some problem, maybe closed", conv)
	} else {
		n := ch.kcp.Input(buf)
		debug.Println("udp->kcp:", conv, n, len(buf), gopp.StrSuf(string(buf), 52))

		if ch.udp_peer_addr == nil ||
			(ch.udp_peer_addr != nil && addr.String() != ch.udp_peer_addr.String()) {
			info.Printf("maybe nat change for client: %s => %s.\n", ch.udp_peer_addr, addr)
			ch.udp_peer_addr = addr
		}
	}
}
예제 #4
0
파일: tunneld.go 프로젝트: kitech/toxtun
func (this *Tunneld) onToxnetFriendLossyPacket(t *tox.Tox, friendNumber uint32, message string, userData interface{}) {
	debug.Println(friendNumber, len(message), gopp.StrSuf(message, 52), time.Now().String())
	buf := bytes.NewBufferString(message).Bytes()
	if buf[0] == 254 {
		buf = buf[1:]
		// kcp包前4字段为conv,little hacky
		conv := binary.LittleEndian.Uint32(buf)
		ch := this.chpool.pool2[conv]
		if ch == nil {
			info.Println("channel not found, maybe has some problem, maybe closed", conv)
		} else {
			n := ch.kcp.Input(buf)
			debug.Println("tox->kcp:", conv, n, len(buf), gopp.StrSuf(string(buf), 52))
		}
	} else {
		info.Println("unknown message:", buf[0])
	}
}
예제 #5
0
파일: tunnelc.go 프로젝트: kitech/toxtun
func (this *Tunnelc) onToxnetFriendLosslessPacket(t *tox.Tox, friendNumber uint32, message string, userData interface{}) {
	debug.Println(friendNumber, len(message), gopp.StrSuf(message, 52))
	buf := bytes.NewBufferString(message).Bytes()
	if buf[0] == 191 { // lossypacket
		buf = buf[1:]
		var conv uint32
		// kcp包前4字段为conv,little hacky
		if len(buf) < 4 {
			errl.Println("wtf")
		}
		conv = binary.LittleEndian.Uint32(buf)
		ch := this.chpool.pool2[conv]
		if ch == nil {
			errl.Println("maybe has some problem")
		}
		n := ch.kcp.Input(buf)
		debug.Println("tox->kcp:", conv, n, len(buf), gopp.StrSuf(string(buf), 52))
	} else {
		info.Println("unknown message:", buf[0])
	}
}
예제 #6
0
파일: tunneld.go 프로젝트: kitech/toxsh
func (this *Tunneld) onToxnetFriendMessage(t *tox.Tox, friendNumber uint32, message string, userData interface{}) {
	debug.Println(friendNumber, len(message), gopp.StrSuf(message, 52))
	friendId, err := this.tox.FriendGetPublicKey(friendNumber)
	if err != nil {
		errl.Println(err)
	}

	pkt := parsePacket(bytes.NewBufferString(message).Bytes())
	if pkt == nil {
		info.Println("maybe not command, just normal message")
	} else {
		if pkt.command == CMDCONNSYN {
			ch := NewChannelWithId(pkt.chidcli)
			ch.conv = this.makeKcpConv(friendId, pkt)
			ch.ip = pkt.remoteip
			ch.port = pkt.remoteport
			ch.toxid = friendId
			ch.kcp = NewKCP(ch.conv, this.onKcpOutput, ch)
			ch.kcp.SetMtu(tunmtu)
			if kcp_mode == "fast" {
				ch.kcp.WndSize(128, 128)
				ch.kcp.NoDelay(1, 10, 2, 1)
			}
			this.chpool.putServer(ch)
			info.Println("channel connected,", ch.chidcli, ch.chidsrv, ch.conv, pkt.msgid)

			repkt := ch.makeConnectACKPacket()
			r, err := this.FriendSendMessage(ch.toxid, string(repkt.toJson()))
			if err != nil {
				debug.Println(err, r)
			}

			appevt.Trigger("newconn")
			appevt.Trigger("connok")
			appevt.Trigger("connact", 1)
			// can connect backend now,不能阻塞,开新的goroutine
			go this.pollServerReadyRead(ch)
		} else if pkt.command == CMDCLOSEFIN {
			if ch, ok := this.chpool.pool2[pkt.conv]; ok {
				info.Println("recv client close fin,", ch.chidcli, ch.chidsrv, ch.conv, pkt.msgid)
				ch.client_socket_close = true
				this.promiseChannelClose(ch)
			} else {
				info.Println("recv client close fin, but maybe server already closed",
					pkt.command, pkt.chidcli, pkt.chidsrv, pkt.conv, pkt.msgid)
			}
		} else {
			errl.Println("wtf, unknown cmmand:", pkt.command, pkt.chidcli, pkt.chidsrv, pkt.conv)
		}

	}
}
예제 #7
0
파일: tunnelc.go 프로젝트: kitech/toxtun
func (this *Tunnelc) copyServer2Client(ch *Channel, pkt *Packet) {
	debug.Println("processing channel data:", ch.chidcli, gopp.StrSuf(pkt.data, 52))
	buf, err := base64.StdEncoding.DecodeString(pkt.data)
	if err != nil {
		errl.Println(err)
	}

	wn, err := ch.conn.Write(buf)
	if err != nil {
		debug.Println(err)
	} else {
		debug.Println("kcp->cli:", wn)
		appevt.Trigger("respbytes", wn, len(pkt.data)+25)
	}
}
예제 #8
0
파일: tunnelc.go 프로젝트: kitech/toxsh
func (this *Tunnelc) onToxnetFriendMessage(t *tox.Tox, friendNumber uint32, message string, userData interface{}) {
	debug.Println(friendNumber, len(message), gopp.StrSuf(message, 52))
	pkt := parsePacket(bytes.NewBufferString(message).Bytes())
	if pkt == nil {
		info.Println("maybe not command, just normal message")
	} else {
		if pkt.command == CMDCONNACK {
			if ch, ok := this.chpool.pool[pkt.chidcli]; ok {
				ch.conv = pkt.conv
				ch.chidsrv = pkt.chidsrv
				ch.kcp = NewKCP(ch.conv, this.onKcpOutput, ch)
				ch.kcp.SetMtu(tunmtu)
				if kcp_mode == "fast" {
					ch.kcp.WndSize(128, 128)
					ch.kcp.NoDelay(1, 10, 2, 1)
				}
				this.chpool.putClientLacks(ch)

				info.Println("channel connected,", ch.chidcli, ch.chidsrv, ch.conv)
				appevt.Trigger("connok")
				appevt.Trigger("connact", 1)
				ch.conn_ack_recved = true
				// can read now,不能阻塞,开新的goroutine
				go this.pollClientReadyRead(ch)
			} else {
				info.Println("maybe conn ack response timeout", pkt.chidcli, pkt.chidsrv, pkt.conv)
				// TODO 应该给服务器回个关闭包
				ch := NewChannelFromPacket(pkt)
				newpkt := ch.makeCloseFINPacket()
				this.tox.FriendSendMessage(friendNumber, string(newpkt.toJson()))
			}
		} else if pkt.command == CMDCLOSEFIN {
			if ch, ok := this.chpool.pool2[pkt.conv]; ok {
				ch.server_socket_close = true
				this.promiseChannelClose(ch)
			} else {
				info.Println("recv server close, but maybe client already closed",
					pkt.command, pkt.chidcli, pkt.chidsrv, pkt.conv)
			}
		} else {
			errl.Println("wtf, unknown cmmand:", pkt.command, pkt.chidcli, pkt.chidsrv, pkt.conv)
		}
	}
}
예제 #9
0
파일: tunnelc.go 프로젝트: kitech/toxtun
func (this *Tunnelc) processUdpReadyRead(addr net.Addr, buf []byte, size int) {
	// info.Println(addr, string(buf), size)
	debug.Println(addr, string(buf), size)
	// kcp包前4字段为conv,little hacky
	if len(buf) < 4 {
		errl.Println("wtf")
	}

	// maybe check ping packet

	// unpack kcp package
	conv := binary.LittleEndian.Uint32(buf)
	ch := this.chpool.pool2[conv]
	if ch == nil {
		errl.Println("maybe has some problem:", conv)
	} else {
		n := ch.kcp.Input(buf)
		debug.Println("udp->kcp:", conv, n, len(buf), gopp.StrSuf(string(buf), 52))
	}
}