func searchKeyword_semihonest(req common.SearchRequest_semihonest) (common.SearchResponse_semihonest, error) {
    var s *C.server = sNew
    if (req.Version == newVersionNum) {
        s = sNew
    } else if (req.Version == oldVersionNum) {
        s =  sOld
    }  else {
        log.Println("Unknown version number: ", req.Version)
    }
    cKeys := (***C.uchar)(C.malloc(C.size_t(kNumThreads) * C.size_t(unsafe.Sizeof(&req))))
    cResultsTemp := (***C.uint8_t)(C.malloc(C.size_t(kNumThreads) * C.size_t(unsafe.Sizeof(&req))))
    cResultsFinal := (**C.uint8_t)(C.malloc(C.size_t(C.BLOOM_FILTER_K) * C.size_t(unsafe.Sizeof(&req))))
    cKeysIndexable := (*[1<<30 - 1]**C.uchar)(unsafe.Pointer(cKeys))
    cResultsTempIndexable := (*[1<<30 - 1]**C.uint8_t)(unsafe.Pointer(cResultsTemp))
    cResultsFinalIndexable := (*[1<<30 - 1]*C.uint8_t)(unsafe.Pointer(cResultsFinal))
    for i := 0; i < kNumThreads; i++ {
        cKeysIndexable[i] = (**C.uchar)(C.malloc(C.size_t(C.BLOOM_FILTER_K) * C.size_t(unsafe.Sizeof(&req))))
        cResultsTempIndexable[i] = (**C.uint8_t)(C.malloc(C.size_t(C.BLOOM_FILTER_K) * C.size_t(unsafe.Sizeof(&req))))
        cKeysIndexableInner := (*[1<<30 - 1]*C.uchar)(unsafe.Pointer(cKeysIndexable[i]))
        cResultsTempIndexableInner := (*[1<<30 - 1]*C.uint8_t)(unsafe.Pointer(cResultsTempIndexable[i]))
        for j := 0; j < int(C.BLOOM_FILTER_K); j++ {
            cKeysIndexableInner[j] = (*C.uchar)(C.CBytes(req.Keys[j]))
            cResultsTempIndexableInner[j] = (*C.uint8_t)(C.malloc((C.size_t(C.NUM_DOCS_BYTES))))
        }
    }
    for i := 0; i < int(C.BLOOM_FILTER_K); i++ {
        cResultsFinalIndexable[i] = (*C.uint8_t)(C.malloc((C.size_t(C.NUM_DOCS_BYTES))))
    }
    slice := int(C.BLOOM_FILTER_SZ) / kNumThreads
    var wg sync.WaitGroup
    wg.Add(kNumThreads)
    for i := 0; i < kNumThreads; i++ {
        go func(index int) {
            defer wg.Done()
            C.runQuery((*C.server)(s),
                        (**C.uchar)(cKeysIndexable[index]),
                        (**C.uint8_t)(cResultsTempIndexable[index]),
                        C.int(index),
                        C.int(index * slice),
                        C.int((index + 1) * slice))
        }(i)
    }
    wg.Wait()
    C.assemblePerThreadResults((*C.server)(s),
                                (***C.uint8_t)(cResultsTemp),
                                (C.int)(kNumThreads),
                                (**C.uint8_t)(cResultsFinal))
    results := make([][]byte, C.int(C.BLOOM_FILTER_K))
    for i := 0; i < int(C.BLOOM_FILTER_K); i++ {
        results[i] = C.GoBytes(unsafe.Pointer(cResultsFinalIndexable[i]), C.int(C.NUM_DOCS_BYTES))
    }
    resp := common.SearchResponse_semihonest{
        Results: results,
    }
    return resp, nil
}
/* Process search request (semihonest adversaries).
package main
import "C"
import (
    "log"
    "net"
    "common"
    "os"
    "fmt"
    "encoding/json"
    "encoding/hex"
    "bufio"
    "github.com/hashicorp/go-msgpack/codec"
    "unsafe"
    "flag"
    "sync"
    "time"
    "strconv"
    "io"
    "bytes"
)
const kNumThreads = 16
var sOld *C.server
var sNew *C.server
var config common.ServerConfig
var oldVersionNum int
var newVersionNum int
var incomingVersionNum int
var incomingUpdates map[int]common.Update
var isMalicious bool
func setupConfig(filename string) (common.ServerConfig, error) {
    config := common.ServerConfig{}
    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 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.SEARCH_REQUEST_MALICIOUS:
            var req common.SearchRequest_malicious
            if err := dec.Decode(&req); err != nil {
                log.Fatalln(err)
            }
            start := time.Now()
            resp, respErr := searchKeyword_malicious(req)
            elapsed := time.Since(start)
            resp.ServerLatency = elapsed
            logLatency(elapsed, "malicious")
            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.SEARCH_REQUEST_SEMIHONEST:
            var req common.SearchRequest_semihonest
            if err := dec.Decode(&req); err != nil {
                log.Fatalln(err)
            }
            start := time.Now()
            resp, respErr := searchKeyword_semihonest(req)
            elapsed := time.Since(start)
            resp.ServerLatency = elapsed
            logLatency(elapsed, "semihonest")
            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.UPDATE_REQUEST_MALICIOUS:
            var req common.UpdateRequest_malicious
            if err := dec.Decode(&req); err != nil {
                log.Fatalln(err)
            }
            updateDoc_malicious(req)
        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.SETUP_REQUEST:
            var req common.SetupRequest
            if err := dec.Decode(&req); err != nil {
                log.Fatalln(err)
            }
            resp, respErr := fastSetup(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.BATCH_START_REQUEST:
            var req common.BatchStartRequest
            if err := dec.Decode(&req); err != nil {
                log.Fatalln(err)
            }
            resp, respErr := startUpdateBatch(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.BATCH_FINISH_REQUEST:
            var req common.BatchFinishRequest
            if err := dec.Decode(&req); err != nil {
                log.Fatalln(err)
            }
            resp, respErr := finishUpdateBatch(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))
        }
    }
}
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 searchKeyword_malicious(req common.SearchRequest_malicious) (common.SearchResponse_malicious, error) {
    var s *C.server = sNew
    if (req.Version == newVersionNum) {
        s = sNew
        log.Println("new version num")
    } else if (req.Version == oldVersionNum) {
        s =  sOld
        log.Println("old version num")
    }  else {
        log.Println("Unknown version number: ", req.Version)
    }
    cKeys := (***C.uchar)(C.malloc(C.size_t(kNumThreads) * C.size_t(unsafe.Sizeof(&req))))
    cResultsTemp := (***C.uint8_t)(C.malloc(C.size_t(kNumThreads) * C.size_t(unsafe.Sizeof(&req))))
    cResultsFinal := (**C.uint8_t)(C.malloc(C.size_t(C.BLOOM_FILTER_K) * C.size_t(unsafe.Sizeof(&req))))
    cKeysIndexable := (*[1<<30 - 1]**C.uchar)(unsafe.Pointer(cKeys))
    cResultsTempIndexable := (*[1<<30 - 1]**C.uint8_t)(unsafe.Pointer(cResultsTemp))
    cResultsFinalIndexable := (*[1<<30 - 1]*C.uint8_t)(unsafe.Pointer(cResultsFinal))
    for i := 0; i < kNumThreads; i++ {
        cKeysIndexable[i] = (**C.uchar)(C.malloc(C.size_t(C.BLOOM_FILTER_K) * C.size_t(unsafe.Sizeof(&req))))
        cResultsTempIndexable[i] = (**C.uint8_t)(C.malloc(C.size_t(C.BLOOM_FILTER_K) * C.size_t(unsafe.Sizeof(&req))))
        cKeysIndexableInner := (*[1<<30 - 1]*C.uchar)(unsafe.Pointer(cKeysIndexable[i]))
        cResultsTempIndexableInner := (*[1<<30 - 1]*C.uint8_t)(unsafe.Pointer(cResultsTempIndexable[i]))
        for j := 0; j < int(C.BLOOM_FILTER_K); j++ {
            cKeysIndexableInner[j] = (*C.uchar)(C.CBytes(req.Keys[j]))
            cResultsTempIndexableInner[j] = (*C.uint8_t)(C.malloc((C.size_t(C.MALICIOUS_DPF_LEN))))
        }
    }
    for i := 0; i < int(C.BLOOM_FILTER_K); i++ {
        cResultsFinalIndexable[i] = (*C.uint8_t)(C.malloc((C.size_t(C.MALICIOUS_DPF_LEN))))
    }
    slice := int(C.BLOOM_FILTER_SZ) / kNumThreads
    var wg sync.WaitGroup
    wg.Add(kNumThreads)
    for i := 0; i < kNumThreads; i++ {
        go func(index int) {
            defer wg.Done()
            C.runQuery_malicious((*C.server)(s),
                                 (**C.uchar)(cKeysIndexable[index]),
                                 (**C.uint8_t)(cResultsTempIndexable[index]),
                                 C.int(index),
                                 C.int(index * slice),
                                 C.int((index + 1) * slice))
        }(i)
    }
    wg.Wait()
    C.assemblePerThreadResults((*C.server)(s),
                                (***C.uint8_t)(cResultsTemp),
                                (C.int)(kNumThreads),
                                (**C.uint8_t)(cResultsFinal))
    results := make([][]byte, C.int(C.BLOOM_FILTER_K))
    for i := 0; i < int(C.BLOOM_FILTER_K); i++ {
        results[i] = C.GoBytes(unsafe.Pointer(cResultsFinalIndexable[i]), C.int(C.MALICIOUS_DPF_LEN))
    }
    resp := common.SearchResponse_malicious{
        Results: results,
    }
    return resp, nil
}