func handleConnection(conn net.Conn) {
    defer conn.Close()
    r := bufio.NewReader(conn)
    w := bufio.NewWriter(conn)
    dec := codec.NewDecoder(r, &codec.MsgpackHandle{})
    enc := codec.NewEncoder(w, &codec.MsgpackHandle{})
    for {
        rpcType, err := r.ReadByte()
        if err != nil {
            if err.Error() == "EOF" {
                break
            } else {
                log.Fatalln(err)
            }
        }
        switch rpcType {
        case common.UPDATE_REQUEST_SEMIHONEST:
            var req common.UpdateRequest_semihonest
            if err := dec.Decode(&req); err != nil {
                log.Fatalln(err)
            }
            updateDoc_semihonest(req)
        case common.UPDATE_REQUEST_MALICIOUS:
            var req common.UpdateRequest_malicious
            if err := dec.Decode(&req); err != nil {
                log.Fatalln(err)
            }
            updateDoc_malicious(req)
        case common.SETUP_REQUEST:
            var req common.MasterSetupRequest
            if err := dec.Decode(&req); err != nil {
                log.Fatalln(err)
            }
            resp, respErr := testSetup(req)
            if err := enc.Encode(&respErr); err != nil {
                log.Fatalln(err)
            }
            if err := enc.Encode(&resp); err != nil {
                log.Fatalln(err)
            }
            if err := w.Flush(); err != nil {
                log.Fatalln(err)
            }
        case common.GET_STATE_REQUEST:
            var req common.GetStateRequest
            if err := dec.Decode(&req); err != nil {
                log.Fatalln(err)
            }
            resp, respErr := getState(req)
            if err := enc.Encode(&respErr); err != nil {
                log.Fatalln(err)
            }
            if err := enc.Encode(&resp); err != nil {
                log.Fatalln(err)
            }
            if err := w.Flush(); err != nil {
                log.Fatalln(err)
            }
        default:
            log.Fatalln(fmt.Errorf("Unknown request type %d", rpcType))
        }
    }
}
/* Dispatch handlers for different message types.
package main
import "C"
import(
    "encoding/json"
    "sync"
    "time"
    "common"
    "os"
    "net"
    "bufio"
    "log"
    "github.com/hashicorp/go-msgpack/codec"
    "fmt"
    "strconv"
    "io"
    "flag"
)
var config common.MasterConfig
var updateList []common.Update
var updateLocks []sync.Mutex
var versionNum int
var versionNumLock sync.Mutex
var maxDocs int
var docVersions []uint32
var numDocs int
var isMalicious bool
var tickTime time.Duration
var numClusters int
func setupConfig(filename string) (common.MasterConfig, error) {
    config := common.MasterConfig{}
    file, err := os.Open(filename)
    if err != nil {
        return config, err
    }
    defer file.Close()
    decoder := json.NewDecoder(file)
    err = decoder.Decode(&config)
    if err != nil {
        return config, err
    }
    return config, nil
}
func logLatency (latency time.Duration, tag string) {
    go func(latency time.Duration, tag string) {
        file, _ := os.Create(config.OutDir + "/" + strconv.Itoa(int(C.NUM_DOCS)) + "_docs_" + strconv.Itoa(int(C.BLOOM_FILTER_SZ)) + "bf_latency_" + tag)
        defer file.Close()
        io.WriteString(file, latency.String())
    }(latency, tag)
}
func start2PC(version int, updateMapCopy map[int]common.Update) {
    commitReq := &common.BatchStartRequest{
        VersionNum:     version,
	    Updates:	updateMapCopy,
        Malicious:      isMalicious, 
    }
    finalCommit := true
    var finalCommitLock sync.Mutex
    var wg1 sync.WaitGroup
    wg1.Add(2 * numClusters)
    for i := 0; i < 2 * numClusters; i+= 1 {
        go func(i int) {
            var commitRespError error
            commitResp := &common.BatchStartResponse{}
            defer wg1.Done()
            common.SendMessage(
                config.Addr[i] + config.Port[i],
                common.BATCH_START_REQUEST,
                commitReq,
                commitResp,
                &commitRespError,
            )
            finalCommitLock.Lock()
            finalCommit = commitResp.Commit
            finalCommitLock.Unlock()
        }(i)
    }
    wg1.Wait()
    finishReq := &common.BatchFinishRequest{
        Commit:     finalCommit,
    }
    var wg2 sync.WaitGroup
    wg2.Add(2 * numClusters)
    for i := 0; i < 2 * numClusters; i += 1 {
        go func(i int) {
            finishResp := &common.BatchFinishResponse{}
            var finishRespError error
            defer wg2.Done()
            common.SendMessage(
                config.Addr[i] + config.Port[i],
                common.BATCH_FINISH_REQUEST,
                finishReq,
                finishResp,
                &finishRespError,
            )
        }(i)
    }
    wg2.Wait()
}
func updateDoc_semihonest(req common.UpdateRequest_semihonest) (common.UpdateResponse_semihonest, error) {
    if req.DocID >= numDocs {
        numDocs = req.DocID + 1
    }
    updateLocks[req.DocID].Lock()
    updateList[req.DocID] = common.Update{
        BF: req.BF,
        MACs: nil,
    }
    docVersions[req.DocID] = req.Version
    updateLocks[req.DocID].Unlock()
    return common.UpdateResponse_semihonest{}, nil
}
func updateDoc_malicious(req common.UpdateRequest_malicious) (common.UpdateResponse_malicious, error) {
    if req.DocID >= numDocs {
        numDocs = req.DocID + 1
    }
    updateLocks[req.DocID].Lock()
    updateList[req.DocID] = common.Update  {
        BF: req.BF,
        MACs: req.MACs,
    }
    docVersions[req.DocID] = req.Version
    updateLocks[req.DocID].Unlock()
    return common.UpdateResponse_malicious{}, nil
}
func getState (req common.GetStateRequest) (common.GetStateResponse, error) {
    docVersionsCopy := make([]uint32, len(docVersions))
    copy(docVersionsCopy, docVersions)
    versionNumLock.Lock()
    resp := common.GetStateResponse{
        NumDocs: numDocs,
        SysVersion: versionNum,
    }
    versionNumLock.Unlock()
    return resp, nil
}
func testSetup (req common.MasterSetupRequest) (common.MasterSetupResponse, error) {
    numDocs = req.NumDocs
    docVersions = req.Versions
    return common.MasterSetupResponse{Test: "success"}, nil
}