github.com/unirita/cuto@v0.9.8-0.20160830082821-aa6652f877b7/master/remote/request.go (about)

     1  // Copyright 2015 unirita Inc.
     2  // Created 2015/04/10 honda
     3  
     4  package remote
     5  
     6  import (
     7  	"bufio"
     8  	"fmt"
     9  	"net"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/unirita/cuto/log"
    14  	"github.com/unirita/cuto/master/config"
    15  	"github.com/unirita/cuto/message"
    16  )
    17  
    18  type response struct {
    19  	msg string
    20  	err error
    21  }
    22  
    23  // 送受信メッセージの終端文字
    24  const MsgEnd = "\n"
    25  
    26  // ホスト名がhost、ポート番号がportのservantへ接続し、ジョブ実行要求を送信する。
    27  // servantから返信されたジョブ実行結果を関数外へ返す。
    28  //
    29  // param : host ホスト名。
    30  //
    31  // param : port ポート番号。
    32  //
    33  // param : req リクエストメッセージ。
    34  //
    35  // return : 返信メッセージ。
    36  //
    37  // return : エラー情報。
    38  func SendRequest(host string, port int, req string, stCh chan<- string) (string, error) {
    39  	const bufSize = 1024
    40  	timeout := time.Duration(config.Job.ConnectionTimeoutSec) * time.Second
    41  
    42  	addr := fmt.Sprintf("%s:%d", host, port)
    43  	conn, err := net.DialTimeout("tcp", addr, timeout)
    44  	if err != nil {
    45  		return ``, err
    46  	}
    47  	defer conn.Close()
    48  
    49  	log.Debug(req)
    50  	_, err = conn.Write([]byte(req + MsgEnd))
    51  	if err != nil {
    52  		return ``, err
    53  	}
    54  
    55  	scanner := bufio.NewScanner(conn)
    56  
    57  	for {
    58  		select {
    59  		case res := <-readResponse(scanner):
    60  			if res.err != nil {
    61  				return ``, res.err
    62  			}
    63  			log.Debug(res.msg)
    64  			if res.msg == message.HEARTBEAT {
    65  				// ハートビートメッセージの場合はバッファサイズを初期化する。
    66  				continue
    67  			} else if strings.HasPrefix(res.msg, message.ST_HEADER) {
    68  				st := res.msg[len(message.ST_HEADER):]
    69  				stCh <- st
    70  				continue
    71  			}
    72  
    73  			return res.msg, nil
    74  		case <-time.After(timeout):
    75  			return ``, fmt.Errorf("Connetion timeout.")
    76  		}
    77  	}
    78  }
    79  
    80  func readResponse(scanner *bufio.Scanner) <-chan *response {
    81  	ch := make(chan *response, 10)
    82  	go func() {
    83  		res := new(response)
    84  		if scanner.Scan() {
    85  			res.msg = scanner.Text()
    86  		} else {
    87  			res.err = scanner.Err()
    88  		}
    89  		ch <- res
    90  		if res.err != nil {
    91  			return
    92  		}
    93  	}()
    94  
    95  	return ch
    96  }