<commit_before>/*
 * net.go
 *
 * Copyright 2017 <NAME>
 */
/*
 * This file is part of netchan.
 *
 * It is licensed under the MIT license. The full license text can be found
 * in the License.txt file at the root of this project.
 */

package netchan

import (
	"crypto/tls"
	"fmt"
	"io"
	"net"
	"net/url"
	"reflect"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)

const netIdleTimeout = 3 * time.Minute

func netDial(address string, tlscfg *tls.Config) (net.Conn, error) {
	if nil == tlscfg {
		return net.Dial("tcp", address)
	} else {
		return tls.Dial("tcp", address, tlscfg)
	}
}

func netListen(address string, tlscfg *tls.Config) (net.Listener, error) {
	if nil == tlscfg {
		return net.Listen("tcp", address)
	} else {
		return tls.Listen("tcp", address, tlscfg)
	}
}

func netReadMsg(conn net.Conn, idleTimeout time.Duration) ([]byte, error) {
	if 0 != idleTimeout {
		// net.Conn does not have idle deadline, so emulate with read deadline on message length
		conn.SetReadDeadline(time.Now().Add(idleTimeout))
	}

	buf := [4]byte{}
	_, err := io.ReadFull(conn, buf[:])
	if nil != err {
		return nil, NewErrTransport(err)
	}

	n := int(buf[0]) | (int(buf[1]) << 8) | (int(buf[2]) << 16) | (int(buf[3]) << 24)
	if 4 > n || configMaxMsgSize < n {
		return nil, ErrTransportMessageCorrupt
	}

	if 0 != idleTimeout {
		// extend read deadline to allow enough time for message to be read
		conn.SetReadDeadline(time.Now().Add(idleTimeout))
	}

	msg := make([]byte, n)
	_, err = io.ReadFull(conn, msg[4:])
	if nil != err {
		return nil, NewErrTransport(err)
	}

	msg[0] = buf[0]
	msg[1] = buf[1]
	msg[2] = buf[2]
	msg[3] = buf[3]

	return msg, nil
}

func netWriteMsg(conn net.Conn, idleTimeout time.Duration, msg []byte) error {
	n := len(msg)
	if 4 > n || configMaxMsgSize < n {
		return ErrTransportMessageCorrupt
	}

	msg[0] = byte(n & 0xff)
	msg[1] = byte((n >> 8) & 0xff)
	msg[2] = byte((n >> 16) & 0xff)
	msg[3] = byte((n >> 24) & 0xff)

	_, err := conn.Write(msg)
	if nil != err {
		return NewErrTransport(err)
	}
<commit_msg>netTransport: implement idle timeout<commit_after>/*
 * net.go
 *
 * Copyright 2017 <NAME>
 */
/*
 * This file is part of netchan.
 *
 * It is licensed under the MIT license. The full license text can be found
 * in the License.txt file at the root of this project.
 */

package netchan

import (
	"crypto/tls"
	"fmt"
	"io"
	"net"
	"net/url"
	"reflect"
	"strconv"
	"strings"
	"sync"
	"sync/atomic"
	"time"
)

const netIdleTimeout = 3 * time.Minute

func netDial(address string, tlscfg *tls.Config) (net.Conn, error) {
	if nil == tlscfg {
		return net.Dial("tcp", address)
	} else {
		return tls.Dial("tcp", address, tlscfg)
	}
}

func netListen(address string, tlscfg *tls.Config) (net.Listener, error) {
	if nil == tlscfg {
		return net.Listen("tcp", address)
	} else {
		return tls.Listen("tcp", address, tlscfg)
	}
}

func netReadMsg(conn net.Conn, idleTimeout time.Duration) ([]byte, error) {
	if 0 != idleTimeout {
		// net.Conn does not have "idle" deadline, so emulate with read deadline on message length
		conn.SetReadDeadline(time.Now().Add(idleTimeout))
	}

	buf := [4]byte{}
	_, err := io.ReadFull(conn, buf[:])
	if nil != err {
		return nil, NewErrTransport(err)
	}

	n := int(buf[0]) | (int(buf[1]) << 8) | (int(buf[2]) << 16) | (int(buf[3]) << 24)
	if 4 > n || configMaxMsgSize < n {
		return nil, ErrTransportMessageCorrupt
	}

	if 0 != idleTimeout {
		// extend read deadline to allow enough time for message to be read
		conn.SetReadDeadline(time.Now().Add(idleTimeout))
	}

	msg := make([]byte, n)
	_, err = io.ReadFull(conn, msg[4:])
	if nil != err {
		return nil, NewErrTransport(err)
	}

	msg[0] = buf[0]
	msg[1] = buf[1]
	msg[2] = buf[2]
	msg[3] = buf[3]

	return msg, nil
}

func netWriteMsg(conn net.Conn, idleTimeout time.Duration, msg []byte) error {
	n := len(msg)
	if 4 > n || configMaxMsgSize < n {
		return ErrTransportMessageCorrupt
	}

	msg[0] = byte(n & 0xff)
	msg[1] = byte((n >> 8) & 0xff)
	msg[2] = byte((n >> 16) & 0xff)
	msg[3] = byte((n >> 24) & 0xff)

	if 0 != idleTimeout {
		// extend read deadline to allow enough time for message to be written
		conn.SetReadDeadline(time.Now().Add(idleTimeout))
	}

	_, err := conn.Write(msg)
	if nil != err {
		return NewErrTransport(err)
	}

{'fraction_non_alphanumeric': 0.1602999765643309, 'fraction_numerical': 0.019451605343332554, 'mean_word_length': 3.619047619047619, 'pattern_counts': {'":': 0, '<': 21, '<?xml version=': 0, '>': 21, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6386325', 'n_tokens_mistral': 1740, 'n_tokens_neox': 1653, 'n_words': 457}